Jhonney的專欄

             ----人見人愛
          隨筆 - 49, 文章 - 1, 評論 - 23, 引用 - 0
          數據加載中……

          ORACLE 關連更新 update select

          $ sqlplus user/pass

          SQL*Plus: Release 9.2.0.6.0 - Production on Wed Aug 2 17:38:39 2006

          Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.


          Connected to:
          Oracle9i Enterprise Edition Release 9.2.0.6.0 - 64bit Production
          With the Partitioning, OLAP and Oracle Data Mining options
          JServer Release 9.2.0.6.0 - Production

          SQL> select * from wwm2;        --要更新的表

          TOWN                         ID
          -------------------- ----------
          222                         222
          111                         111
          ww'jj                       111
          llll                       1111
          dddd                       2222
          lllldf                      111
          lllldf                      111
          dsafdf                      111
          3435                        111
          ljjjjj                      222
          dsafdf                      111
          TOWN                         ID
          -------------------- ----------
          3435                        111
          ljjjjj                      222

          SQL> select * from wwm5;            --更新的條件表
          TOWN                         ID
          -------------------- ----------
          lllldf                      111
          test                       9984
          SQL> select wwm2.* from wwm2,wwm5 where wwm2.id=wwm5.id
            2  /
          TOWN                         ID
          -------------------- ----------
          111                         111
          ww'jj                       111
          lllldf                      111
          lllldf                      111
          dsafdf                      111
          3435                        111
          dsafdf                      111
          3435                        111
          8 rows selected.
          所以,每次需要更新8條數據就是正確的.
          相信程序員是通過以下類似的SQL更新的,這是錯誤的,因為沒有加WHERE
          SQL>  update wwm2 set wwm2.town=(select wwm5.town from wwm5 where wwm5.id=wwm2.id)
            2  /
          13 rows updated.
          SQL> select * from wwm2;
          TOWN                         ID
          -------------------- ----------
                                      222
          lllldf                      111
          lllldf                      111
                                     1111
                                     2222
          lllldf                      111
          lllldf                      111
          lllldf                      111
          lllldf                      111
                                      222
          lllldf                      111
          TOWN                         ID
          -------------------- ----------
          lllldf                      111
                                      222
          13 rows selected.
          可以看到13條記錄被更新,符合條件的更新正確,不符合條件的也更新為NULL.以下是正確的方法
          方法一:
          SQL> update wwm2
            2  set town=(select town from wwm5 where wwm5.id=wwm2.id)
            3  where id=(select wwm5.id from wwm5 where wwm5.id=wwm2.id)
            4  /
          8 rows updated.
          方法二:    與方法一道理相同,這里需要掌握EXIST的相關用法.
          SQL> update wwm2
             set town=(select town from wwm5 where wwm5.id=wwm2.id)
             where exists (select 1 from wwm5 where wwm5.id=wwm2.id)
          8 rows updated.
          方法三:
          SQL> update (select a.town atown,a.id aid,b.town btown,b.id bid from wwm2 a,wwm5 b where a.id=b.id)
            2  set atown=btown
            3  /
          set atown=btown
              *
          ERROR at line 2:
          ORA-01779: cannot modify a column which maps to a non key-preserved table
            1* alter table wwm5 add primary key (id)
          SQL> /
          Table altered.
            1  update (select a.town atown,a.id aid,b.town btown,b.id bid from wwm2 a,wwm5 b where a.id=b.id)
            2*  set atown=btown
          SQL> /
          8 rows updated.
          這種方法的局限性就是需要PRIMARY 的支持.
          方法四:
            1  declare
            2  cursor cur_wwm is select town,id from wwm5;
            3  begin
            4     for my_wwm in cur_wwm loop
            5     update wwm2 set town=my_wwm.town
            6     where id=my_wwm.id;
            7     end loop;
            8* end;
          SQL> /
          PL/SQL procedure successfully completed.
          SQL> select * from wwm2;
          TOWN                         ID
          -------------------- ----------
          222                         222
          lllldf                      111
          lllldf                      111
          llll                       1111
          dddd                       2222
          lllldf                      111
          lllldf                      111
          lllldf                      111
          lllldf                      111
          ljjjjj                      222
          lllldf                      111
          TOWN                         ID
          -------------------- ----------
          lllldf                      111
          ljjjjj                      222
          這個方法是最靈活的了.
          方法五:
          注意,方法五只能適用于WWM5是WWM2的子集的時候.
            1   merge into wwm2
            2   using (select town,id from wwm5) b
            3   on (wwm2.id=b.id)
            4   when matched then update set town=b.town
            5* when not matched then insert (town,id) values (null,null)
          SQL> /
          9 rows merged.
          SQL> select * from wwm2;
          TOWN                         ID
          -------------------- ----------
                                            ---注意這個地方,被插入了一個空值.因為WWM5的ID=9984在WWM2中不能匹配,根本原因是ORACLE9必須有WHEN NOT MATCHED子句,但是ORACLE10可以不許要,也就是ORACLE10可以不寫WHEN NOT MATCHED ,就不必插入NULL值了,為解決這個問題,下一步會DELETE WWM5的ID=9984,這樣一來就不會執行WHEN NOT MATCHED
          222                         222
          lllldf                      111
          lllldf                      111
          llll                       1111
          dddd                       2222
          lllldf                      111
          lllldf                      111
          lllldf                      111
          lllldf                      111
          ljjjjj                      222
          TOWN                         ID
          -------------------- ----------
          lllldf                      111
          lllldf                      111
          ljjjjj                      222
          14 rows selected.
          SQL> delete from wwm5 where id=9984;
          1 row deleted.
          SQL>  1   merge into wwm2                            
          SQL>   2   using (select town,id from wwm5) b
          SQL>   3   on (wwm2.id=b.id)
          SQL>   4   when matched then update set town=b.town
          SQL>   5* when not matched then insert (town,id) values (null,null)
          SQL> /
          8 rows merged.
           
                 以上就是5種關連更新的例子了,希望能給開發人員解惑.
           
          說明:如果select 子句可以返回多行記錄,但返回適合where條件的記錄只能是唯一的,否則將會報返回單行的select子句返回多行的錯誤,因為update只能跟據此處的where子句(內層where)進行相應記錄的匹配更新,一次只能是一條。

          posted on 2010-06-25 19:30 Jhonney 閱讀(17204) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 顺平县| 苍山县| 榆林市| 梁山县| 平和县| 上饶县| 阿勒泰市| 历史| 余干县| 改则县| 长阳| 英德市| 定兴县| 阜南县| 育儿| 安国市| 博客| 陵水| 攀枝花市| 开封县| 比如县| 梧州市| 横山县| 仙桃市| 胶州市| 丹东市| 永昌县| 永新县| 东辽县| 同德县| 青海省| 天等县| 偏关县| 东莞市| 普陀区| 和平县| 河南省| 堆龙德庆县| 徐闻县| 班玛县| 平安县|