注意:  关键的地方是where 语句的加入. 在11G中, 如果不加11G , 或造成除匹配的行数更新为相应的值之后, 其余的会变成负数.

所以,执行前需要测试, 普通办法就是:  先查看需要更新的数量即连接的数量究竟有多少行, 然后update 之后多少行, 才能确定条件是否正确.

最终完成的2个 SQL, 经过检验, 放心食用:

 1 :   通过关联表查询获取需要更新的 多列 数据更新. 注意Exists子句的必要性
UPDATE SFISM4.R_DT_DIP_TRACEABILITY_T B
SET (B.CURRENT_QTY, B.UPDATE_TIME, B.UPDATE_USER)=
(SELECT DECODE(SIGN(B.CURRENT_QTY - A.KP_COUNT),
-1,
0,
B.CURRENT_QTY - A.KP_COUNT),
SYSDATE,
:VUSER
FROM SFIS1.C_DT_DIP_BOM_T A, SFISM4.R_MO_BASE_T C
WHERE A.BOM_NO = B.BOM_NO
AND B.BOM_NO = C.KEY_PART_NO
AND A.KEY_PART_NO = B.KEY_PART_NO
AND C.MO_NUMBER =:VBOM
AND B.TRAC_LOT =:VTRACELOT)
WHERE B.TRAC_LOT =:VTRACELOT
AND EXISTS (SELECT 1
FROM SFIS1.C_DT_DIP_BOM_T AA
WHERE B.BOM_NO = AA.BOM_NO
AND B.KEY_PART_NO = AA.KEY_PART_NO)
UPDATE SFISM4.R_REEL_TRACKING_T A
SET A.REMAIN_QTY =
(SELECT B.REEL_QTY
FROM SFISM4.R_MMS_STOCK_SMT_SA_DETAIL_T B
WHERE A.REEL_ID = B.REEL_ID
AND A.REMAIN_QTY <0
AND A.REMAIN_QTY <> B.REEL_QTY)
WHERE EXISTS (SELECT 1
FROM SFISM4.R_MMS_STOCK_SMT_SA_DETAIL_T B
WHERE A.REEL_ID = B.REEL_ID
AND A.REMAIN_QTY <0
AND A.REMAIN_QTY <> B.REEL_QTY);
 
2: 如上简化版.
UPDATE SFISM4.R_REEL_TRACKING_T A
SET A.REMAIN_QTY =
(SELECT B.REEL_QTY
FROM SFISM4.R_MMS_STOCK_SMT_SA_DETAIL_T B
WHERE A.REEL_ID = B.REEL_ID
AND A.REMAIN_QTY <0
AND A.REMAIN_QTY <> B.REEL_QTY)
WHERE EXISTS (SELECT 1
FROM SFISM4.R_MMS_STOCK_SMT_SA_DETAIL_T B
WHERE A.REEL_ID = B.REEL_ID
AND A.REMAIN_QTY <0
AND A.REMAIN_QTY <> B.REEL_QTY);
 
从一开始有了想法, 找到的相应one step by step实验过程.
 

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) -- 表连接之后, 更新视图的方式很好理解. 但是需要primary key.
  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的子集的时候. (新特性 merge Into,哎呀! 不想学.....)
  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)进行相应记录的匹配更新,一次只能是一条。
    

参考 网址: http://www.blogjava.net/Jhonney/archive/2010/06/25/324503.html

ORACLE 关连更新 update select的更多相关文章

  1. ORACLE 通过连接查询更新 update select

    注意:  关键的地方是where 语句的加入. 在11G中, 如果不加11G , 或造成除匹配的行数更新为相应的值之后, 其余的会变成负数. 所以,执行前需要测试, 普通办法就是:  先查看需要更新的 ...

  2. oracle 中更新update不成功的原因

    oracle 中执行insert into 与delete 都正常,但是执行update 却没有反应. 原因: 是因为记录锁.这种只有update无法执行其他语句可以执行的其实是因为记录锁导致的,在o ...

  3. oracle 关联更新

    不多说了,我们来做实验吧. 创建如下表数据 select * from t1 ; select * from t2; 现需求:参照T2表,修改T1表,修改条件为两表的fname列内容一致. 方式1,u ...

  4. Oracle并行更新的两种方式(merge/update内联视图)

    对于Oracle的两表联合更新的场景(有A.B两表,以A.id=B.id关联,根据B表中的记录更新A表中的相应字段),一般有update内联视图和merge两种方式,下面举例介绍:   创建用例表: ...

  5. oracle 批量更新之update case when then

      oracle 批量更新之update case when then CreationTime--2018年8月7日15点51分 Author:Marydon 1.情景描述 根据表中同一字段不同情况 ...

  6. mysql 各种级联查询后更新(update select).

    mysql  各种级联查询后更新(update select). CREATE TABLE `tb1` (   `id` int(11) NOT NULL,   `A` varchar(100) de ...

  7. insert、update select from

    1.insert select from <一棵树-博客园> 收集整理,转载请注明出处! 使用SELECT INTO 和 INSERT INTO SELECT 表复制语句了. 1.INSE ...

  8. update select

    update中加入select 最常用的update语法是:UPDATE <table_name>SET <column_name1> = <value>, SET ...

  9. Oracle中的 UPDATE FROM 解决方法

    转:http://www.cnblogs.com/JasonLiao/archive/2009/12/23/1630895.html Oracle中的 UPDATE FROM 解决方法 在表的更新操作 ...

随机推荐

  1. 2015年9月30日html表单笔记

    Asp.net是盖房子,那么html就是里面的砖头. 表单是非常重要的,为什么要使用表单呢?因为表单可以向服务器传输数据. 一般用form表单来传输数据. BS程序的执行模型具体流程是,个人电脑在表单 ...

  2. IIS中访问自己开发的Webservice site就自动停止,尝试重启IIS和重启服务器都不能解决。

    今天在加班的时候发现一个奇怪的问题,IIS里面我们自己开发的Webservice site一访问就自动停止.尝试重启IIS和重启服务器都不能解决.后台windows events报错信息是The Mo ...

  3. jquery判断文本域长度

    <div id="result">您还可以输入100字</div> <textarea name="content" id=&qu ...

  4. python学习之列表

    #coding:utf-81.#reverse方法将列表的元素反向存放,改变了原列表但不返回值x=[5,2,4,3,8]x.reverse() #x[::-1] 不改变list反向排序print x ...

  5. CSS3 keyframes动画实现弹跳效果

    首先,“回到顶部”.“用户反馈”这两个按钮是通过定位放在左下角上. (1)“回到顶部”的按钮只有当滚动条有出现下滑时才出现 (2)“用户反馈”按钮,用户刚打开时会抖动一下,引起用户的注意,然后才定住. ...

  6. 你知道用AngularJs怎么定义指令吗?

    前言 最近学习了下angularjs指令的相关知识,也参考了前人的一些文章,在此总结下. 欢迎批评指出错误的地方.   Angularjs指令定义的API AngularJs的指令定义大致如下 ang ...

  7. Lucene教程具体解释

    (建立索引)] )中生成的索引文件的存放地址.详细步骤简单介绍例如以下: 1.创建Directory对象,索引目录 2.创建IndexSearch对象,建立查询(參数是Directory对象) 3.创 ...

  8. careercup-递归和动态规划 9.6

    9.6 实现一种算法,打印n对括号的全部有效组合(即左右括号正确配对). 类似leetcode:Generate Parentheses 解法: 从头开始构造字符串,从而避免出现重复字符串.在这个解法 ...

  9. C# Attribute (上)——Attribute初体验

      原始出处 .作者信息和本声明.否则将追究法律责任.http://liutiemeng.blog.51cto.com/120361/29201 小序:          注意:本次小序颇长而且没什么 ...

  10. 自定义URL Scheme完全指南

    iPhone / iOS SDK 最酷的特性之一就是应用将其自身”绑定”到一个自定义 URL scheme 上,该 scheme 用于从浏览器或其他应用中启动本应用. 注册自定义 URL Scheme ...