我做了一下UPDATE关联表的思路总结,希望对不知道的同学有帮助!

我最近一直想研究一下UPDATE语句,尤其是多表关联 UPDATE的时候,很容易出问题,于是我就在PUB上问,在资料上查,现在我终于弄明白了。

对我帮助的帖子来源于http://www.itpub.net/showthread. ... 10&pagenumber=1

我把实验的思路整理如下,希望对不知道的人有帮助!

我的结论是这样的
更新表的方式有三种方法
1、
其中最普通的是update t1 set b=(select b from t2 where t1.a=t2.a);
但是,要注意空值的影响,
如果怕空值的影响,要写成
update t1 set b= (select b from t2 where t1.a=t2.a)
where exists
(select 1 from t2 where t1.a=t2.a);

2、
update (
select /*+use_hash(t1,t2)*/ t1.b b1,t2.b b2
from t1,t2 where t1.a=t2.a)
set b1=b2;

这种方法效率高,但是要注意两个关联字段都要有唯一性索引!

这种方式我试过了,确实超级快。

3、存储过程

SQL> declare
2 cursor c is
3 select t1.*,t1.rowid from t1;
4 begin
5 for c1 in c loop
6 update t1 set b=
7 (select b from t2 where a=c1.a)
8 where rowid=c1.rowid
9 and
10 exists
11 (select 1 from t2 where c1.a=t2.a);
12 end loop;
13 end;
14 /

但是还是要注意要有exists的语句,否则一样解决不了空值问题

下面实验如下:

SQL> select * from t1;

A B
---------- ----------
1 1
2 2
3 4
4 4
1
2
4

已选择7行。

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6

SQL> update t1 set b=(select b from t2 where t1.a=t2.a);

已更新7行。

SQL> select * from t1;

A B
---------- ----------
1 2
2 5
3 7
4
1 2
2 5
4

已选择7行。

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6

SQL>
现在ROLLBACK还原,还是原来表的记录如下,加EXISTS操作看看有什么变化
SQL> select * from t1;

A B
---------- ----------
1 1
2 2
3 4
4 4
1
2
4

已选择7行。

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6

SQL> update t1 set b= (select b from t2 where t1.a=t2.a)
2 where exists
3 (select 1 from t2 where t1.a=t2.a);

已更新5行。

SQL> select * from t1;

A B
---------- ----------
1 2
2 5
3 7
4 4
1 2
2 5
4

已选择7行。

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6

SQL>

谢谢!
现在我实验明白了,如果不加
where exists
(select 1 from t2 where t1.a=t2.a);

t1表的a,b字段有4,4的一条记录,由于在t2表中a,b字段不存在a字段值为4的记录.这样在UPDATE的时候,在t2表中找不到就会用null 去UPDATE t1表的4,4为4,null,这可不是我们愿意看到的.

但加了那个EXISTS,问题就避免了。

UPDATE关联表容易出现的第二个错误,也就是著名的
ORA-01427: 单行子查询返回多个行

在这里也能得到实验

回滚原来那两张表

SQL> rollback;

回退已完成。

SQL> select * from t1;

A B
---------- ----------
1 1
2 2
3 4
4 4
1
2
4

已选择7行。

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6

SQL> update t2 set b= (select b from t1 where t2.a=t1.a);
update t2 set b= (select b from t1 where t2.a=t1.a)
*
第 1 行出现错误:
ORA-01427: 单行子查询返回多个行

SQL>
注意到,如果两张表完全一致,t1.a完全和t2.a一一对应,都是唯一的,那就不可能出现这样错误

如果两边不一致,比如t1的a值多余t2的a值或者反过来,我们就要特别注意了。

讲白点就是,多的表允许用少的表来更新,多的表的反正都被少的那个表更新(说准确点应该是少的表都要是唯一的a记录)

少的表,不允许被多的表来更新!

再举个例子
如果两边都有重复,那别管是利用t1更新t2还是利用t2更新t1都别想成功了

SQL> insert into t1 values (3,5);

已创建 1 行。

SQL> insert into t2 values (3,8);

已创建 1 行。

SQL> select * from t1;

A B
---------- ----------
3 5
1 1
2 2
3 4
4 4
1
2
4

已选择8行。

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6
3 8

SQL> update t1 set b=(select b from t2 where t1.a=t2.a);
update t1 set b=(select b from t2 where t1.a=t2.a)
*
第 1 行出现错误:
ORA-01427: 单行子查询返回多个行

SQL> update t2 set b=(select b from t1 where t2.a=t1.a);
update t2 set b=(select b from t1 where t2.a=t1.a)
*
第 1 行出现错误:
ORA-01427: 单行子查询返回多个行

SQL>

做完这些后,听说有另外一种方法能更高效的更新,于是再做实验

就是如下方法了,但是报错了

SQL> update (
2 select /*+use_hash(t1,t2)*/ t1.b b1,t2.b b2
3 from t1,t2
4 where t1.a=t2.a)
5 set b1=b2;
set b1=b2
*
第 5 行出现错误:
ORA-01779: 无法修改与非键值保存表对应的列

听说这种方法要保证两表都是唯一值才可以,只好删除掉重复记录

SQL> delete t1 where rowid in (select rid from(select rowid rid,row_number() ove
r(partition by a order by a desc) rn from t1 )where rn > 1) ;

已删除3行。

SQL> select * from t1;

A B
---------- ----------
1 1
3 4
2
4

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6
接着再更新,哇,又报错

SQL> update (
2 select /*+use_hash(t1,t2)*/ t1.b b1,t2.b b2
3 from t1,t2
4 where t1.a=t1.b)
5 set b1=b2;
set b1=b2
*
第 5 行出现错误:
ORA-01779: 无法修改与非键值保存表对应的列

是不是要建唯一性索引才可以呢?
SQL> create unique index indx_t1_a on t1(a);

索引已创建。

SQL> create unique index indx_t2_a on t2(a);

索引已创建。

再看看,这下可以了,看来网络上说的这种方法高效,但是也挺苛刻的,还要保证唯一性索引,两张表都要保证

SQL> update (
2 select /*+use_hash(t1,t2) */t1.b b1,t2.b b2
3 from t1,t2
4 where t1.a=t2.a)
5 set b1=b2;

已更新3行。

SQL>
SQL> select * from t1;

A B
---------- ----------
1 2
3 7
2 5
4

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6

以上做了这么多实验,收获不小,也谢谢PUB上的兄弟的帮忙,不过后来想存储过程实现是不是也实验一把呢,算是对这个多表更新的一种全面的总结了。

再实验吧

SQL> rollback;

回退已完成。

SQL> select * from t1;

A B
---------- ----------
1 1
3 4
2
4

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6

SQL> declare
2 cursor c is
3 select t1.*,t1.rowid from t1;
4 begin
5 for c1 in c loop
6 update t1 set b=
7 (select b from t2 where a=c1.a)
8 where rowid=c1.rowid;
9 end loop;
10 end;
11 /

PL/SQL 过程已成功完成。

SQL> select * from t1;

A B
---------- ----------
1 2
3 7
2 5
4

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6

SQL>

这个更新应该和普通的第一种更新要考虑的东西是一样的吧,会不会有空值的因素在里面呢?

测试,果然,这个存储过程更新的方法也要考虑空值才可以,否则也会不对,入下

SQL> select * from t1;

A B
---------- ----------
1 2
3 7
2 5
4

SQL> select * from t2;

A B
---------- ----------
1 2
2 5
3 7
6

SQL> delete from t2 where a=1;

已删除 1 行。

SQL> commit;

提交完成。

SQL> select * from t2;

A B
---------- ----------
2 5
3 7
6

SQL> declare
2 cursor c is
3 select t1.*,t1.rowid from t1;
4 begin
5 for c1 in c loop
6 update t1 set b=
7 (select b from t2 where a=c1.a)
8 where rowid=c1.rowid;
9 end loop;
10 end;
11 /

PL/SQL 过程已成功完成。

SQL> select * from t1;

A B
---------- ----------
1
3 7
2 5
4

SQL>

也是需要修改的,代码如下

SQL> select * from t1;

A B
---------- ----------
1 2
3 7
2 5
4

SQL> select * from t2;

A B
---------- ----------
2 5
3 7
6

SQL> declare
2 cursor c is
3 select t1.*,t1.rowid from t1;
4 begin
5 for c1 in c loop
6 update t1 set b=
7 (select b from t2 where a=c1.a)
8 where rowid=c1.rowid
9 and
10 exists
11 (select 1 from t2 where c1.a=t2.a);
12 end loop;
13 end;
14 /

PL/SQL 过程已成功完成。

SQL> select * from t1;

A B
---------- ----------
1 2
3 7
2 5
4

SQL>

这下没空值了

到这里为止,我的UPDATE多表关联的研究终于告一段落了,收获不小,希望看到我这个实验的,原先也不的清楚的兄弟们能有收获!

oralc UPDATE关联表的思路总结相关推荐

  1. [K/3Cloud] KSQL 关联表更新字段Update语法

    关联表更新字段 UPDATE tmp369faa3f7d224b0595670425008 as t1 SET FStatus=-1 where exists(select 1 from t_BD_S ...

  2. update关联其他表批量更新数据

    为了做分析,需要整合一些数据到一个表中,涉及到通过主键关联多个表,获取其中的某些字段的值,通过update可以简单实现,找了一篇文章,挺不错: 批量更新表时,update一个表的列时,需要依赖另外的表 ...

  3. update关联其他表批量更新数据-跨数据库-跨服务器Update时关联表条件更新

    1.有时在做项目时会有些期初数据更新,从老系统更新到新系统.如果用程序循环从老系统付给新系统. 2.有时在项目中需要同步程序,或者自动同步程序时会有大量数据更新就可能用到如下方法了. 3.为了做分析, ...

  4. oracle里update+where,Oracle 关联表更新 update ,where exists

    表A ID NAME AGE SEX BOOK 1 小丑1 12 男 数据结构 2 小丑2 22 女 人工智能 表B ID AGE SEX COMPUTER 1 00 applet 2 00 thin ...

  5. java多对多关联数据操作,hibernate实施多对多关联查询时,关联表数据被删除

    hibernate执行多对多关联查询时,关联表数据被删除 本帖最后由 binbb521 于 2012-12-04 11:48:29 编辑 S2SH框架开发的网站,执行两个多对多关系的表查询时,关联两个 ...

  6. mysql死锁和索引的关系_奇怪的mysql死锁,当有外键索引的时候,会需要请求对关联表的锁吗?...

    请教数据库死锁问题,现象是在回复帖子的时候出现死锁 以下是mysql show innodb status结果: InnoDB |      | =========================== ...

  7. 关联表多数据的批量insert (批量导入,测试19W条数据用时46秒)

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 一.业务需求 :作多个批量导入 ,根据业务不同,每条数据导入前作各种验证,             ...

  8. mysql update 联合更新_Mysql update多表联合更新的方法小结

    下面我建两个表,并执行一系列sql语句,仔细观察sql执行后表中数据的变化,很容易就能理解多表联合更新的用法 student表 class表 1. 执行 UPDATE student s , clas ...

  9. 两表关联更新 mysql_MySQL多表更新(关联表更新)

    在开发过程中,有时会遇到需要将某张表的字段值根据条件动态地更新到另一张表字段的问题,即通过一张表的字段修改另一张关联表中的内容.比如,存在两张表A(表名:test_a).B(表名:test_b),他们 ...

最新文章

  1. Dos批处理常用命令大全入门
  2. python中赋值不正确的_python中的“赋值与深浅拷贝”
  3. Python基础教程:Python pass语句详解
  4. php floatval_php floatval()函数的用法详解
  5. 2.2. 全国各地ISP IP表
  6. Typecho中的gravatar头像无法加载
  7. git 存在多个commit 时将修改,追加到某次commit 上
  8. postman插件4.1.3的安装(亲测,可以用)
  9. c语言for语句10内的累乘,c语言累加累乘教案.doc
  10. C++跨平台开源库 之三
  11. 对120年的奥运数据进行了可视化分析
  12. selenium IED安装
  13. 电脑能复制不能粘贴的问题
  14. php汽车租赁网站_ThinkPHP实战开发汽车租赁网站项目教程
  15. 爬取古诗文网的推荐古诗
  16. 美团开源Graver框架:用“雕刻”诠释iOS端UI界面的高效渲染
  17. 【Verilog基础】ROM IP 核基础知识
  18. husky实现git commit规范
  19. Python爬虫实战+Scrapy框架 爬取当当网图书信息
  20. Linux通过mac地址查找ip地址

热门文章

  1. Go实现简单的TCP服务端客户端通信(有黏包)
  2. C语言第十九讲——函数(2)
  3. Python模块介绍(如何安装、使用)
  4. c#:mvc单选按钮(性别)
  5. nodeName学习
  6. ARM 立即数范围以及合法立即数
  7. 【毕设论文——必修篇】如何正确引用参考文献?让参考文献格式变标准
  8. 旋翼回收火箭系列博客-火箭总体设计
  9. 第一次博客作业成绩汇总
  10. 大蒜素暴露促进污泥发酵的关键机制