注意:  关键的地方是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——外连接查询

    一.问题描述 有时我们为了保留某个表中的数据,而该表中的数据在另外一个关联表中未必都存在对应,此时就应该试用外连接查询. 比如:两个表,产品表和子产品表 注:子产品的parent_product_id ...

  3. 【学亮开讲】Oracle内外连接查询20181119

    --内连接查询 --需求:查询显示业主编号.业主名称.业主类型名称 select os.id 业主编号,os.name 业主名称,ot.name 业主类型名称 from t_owners os,t_o ...

  4. mysql 全连接和 oracle 全连接查询、区别

    oracle的全连接查询可以直接用full on,但是在mysql中没有full join,mysql使用union实现全连接. oracle的全连接 select * from a full joi ...

  5. oracle 之 连接查询

    where 连接 select * from a,b //使用的是笛卡尔乘积  显示 a.count*b.count 条数 select * from a,b where a.id=b.id 其实只是 ...

  6. C#通过SqlConnection连接查询更新等操作Sqlserver数据库

    Sqlserver数据库连接方式有多种,这里只介绍最常用的通过SqlConnection和Sqlserver数据库用户名和密码验证来进行操作数据库. 数据库连接字符串: string connStri ...

  7. Oracle学习笔记五 SQL命令(三):Group by、排序、连接查询、子查询、分页

    GROUP BY和HAVING子句 GROUP BY子句 用于将信息划分为更小的组每一组行返回针对该组的单个结果 --统计每个部门的人数: Select count(*) from emp group ...

  8. MySql的连接查询

    类似于oracle的连接查询,mysql连接查询也有左外连接.右外连接.内连接查询.但是,不同的是没有直接 的全外连接查询. 这里介绍MySql的连接查询: 这里已两张表为例:STUDENT 表 和 ...

  9. IBatis.Net 表连接查询(五)

    IBatis.Net之多表查询: 一.定制实际对应类的方式 首先配置多表的测试数据库,IBatis.Net之Oracle表连接查询配置: 首先新建两张表如下: 为两张表建立外键: ALTER TABL ...

随机推荐

  1. 生产者消费者两种实现:wait/notifyAll和Lock/Condition

    1.wait/notifyAll /** * 面试题:写一个固定容量同步容器,拥有put和get方法,以及getCount方法, * 能够支持2个生产者线程以及10个消费者线程的阻塞调用 * * 使用 ...

  2. windows 8,关闭随意窗体都提示“已停止工作”的解决的方法

           电脑用的好好的,突然出现了关闭随意窗体都提示"已停止工作",每次都是这样.想想也就是偶尔优化一下,近期也没有改动过什么系统设置呀,突然想到昨晚JLink_V8固件丢失 ...

  3. FastAdmin 新年福袋进行中

    FastAdmin 新年福袋进行中 2019新年福袋活动正在进行中 https://www.fastadmin.net/act/20190101/springfestival.html

  4. 我 支持 使用 async await

    这篇文章原来的 标题 是 <我 反对 使用 async await>, 但经过后来的一些研究, 发现 async await 是 良性 的, 所以 我把 标题 改成了 <我 支持 使 ...

  5. Zuul Pre和Post过滤器

    一.项目架构图 二.前置过滤器 @Component public class TokenFilter extends ZuulFilter{ @Override public String filt ...

  6. Eureka Client的使用

    1. 新建工程 下一步,名字叫client 选择Cloud Discovery->Eureka Discovery 下一步后,点击完成 2. 在ClientApplication文件中增加Ena ...

  7. openLayer3地图的使用心得

    准备运行环境: 1)Portable Basemap Server(PBS)用于创建地图服务 官网网址:http://geopbs.codeplex.com/ 如何创建底图服务?操作步骤如下: 如果启 ...

  8. nginx配置遇到的一个大坑

    鄙人负责的项目即将上线,今天团队伙伴反应网站上的图片,有的可以显示有的不可以显示报404,找我看看问题. 我心想啊,404,应该是没有文件才出的,于是,我直接上nginx服务器上查看,检查路径下是否有 ...

  9. python 计算校验和

    校验和是经常使用的,这里简单的列了一个针对按字节计算累加和的代码片段.其实,这种累加和的计算,将字节翻译为无符号整数和带符号整数,结果是一样的. 使用python计算校验和时记住做截断就可以了. 这里 ...

  10. 转---CentOS安装Oracle数据库详细介绍及常见问题汇总

    一.安装前准备 1.软件硬件要求 操作系统:CentOS 6.4(32bit)Oracle数据库版本:Oracle 10g(10201_database_linux32.zip)最小内存:1G(检查命 ...