• [转]oracle update set select from 关联更新


    本文转自:http://blog.csdn.net/disiwei1012/article/details/52589181

    http://www.blogjava.net/Jhonney/archive/2010/06/25/324503.html

    $ 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)进行相应记录的匹配更新,一次只能是一条。
  • 相关阅读:
    java8 localdate 使用
    关于解决多个ifelse的探索(一)
    celery_worker异常退出
    宝塔面板实用教程(1):只需10分钟部署升讯威在线客服系统
    1个程序员单干之:怎样给我的升讯威在线客服系统编写堪比 MSDN 的用户手册
    .net core 和 WPF 开发升讯威在线客服系统:调用百度翻译接口实现实时自动翻译
    .net core 和 WPF 开发升讯威在线客服系统:怎样实现拔网线也不丢消息的高可靠通信(附视频)
    fetch API获取返回值的方式
    ant design charts 获取后端接口数据展示
    Java代码实现grpc服务
  • 原文地址:https://www.cnblogs.com/freeliver54/p/6610097.html
Copyright © 2020-2023  润新知