oracle的表更新问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle的表更新问题相关的知识,希望对你有一定的参考价值。

梳理以前的笔记,找不到更新这一项了,抛200分,希望大家解答的详细点,我好重新做笔记。

简单的说就是2张表,根据其中一张表的信息来更新另外一张表

比如说 A表 id,name,result
B表 id,name,result,remark

更新要求: B表和A表ID相同时,将B表的name,result,remark更新到A表对应的行中
B表和A表ID不相同时,保留A表的原数据不动。

SQL要求:1.用SQL方式更新。
2.用过程(或者function)方式更新

3.上述2种方式均不适用merge函数。
PS:1.之前说漏了一点要求,如果有通过临时表更新的方法,也请写进去吧,谢谢。
2.保障正确性的前提下,越全面越好,依此原则选定最佳答案。

先建立一个结构一模一样的表emp1,并为其插入部分数据
create table emp1
as
select * from emp where deptno = 20;
update掉emp1中的部分数据
update emp1
set sal = sal 100,
comm = nvl(comm,0) 50
然后我们试着使用emp1中数据来更新emp中sal 和 comm这两列数据。
我们可以这么写
Update emp
Set(sal,comm) = (select sal,comm. From emp1 where emp.empno = emp1.empno)
Where exists (select 1 from emp1 where emp1.empno = emp.empno)
请你尤其注意这里的where子句,你可以尝试不写where子句来执行以下这句话,你将会使得emp中的很多值变成空。
这是因为在oracle的update语句中如果不写where子句,oracle将会默认的把所有的值全部更新,即使你这里使用了子查询并且某在值并不能在子查询里找到,你就会想当然的以为,oracle或许将会跳过这些值吧,你错了,oracle将会把该行的值更新为空。
我们还还可以这么写:
update (select a.sal asal,b.sal bsal,a.comm acomm,
b.comm bcomm from emp a,emp1 b where a.empno = b.empno)
set asal = bsal,
acomm = bcomm;
这里的表是一个类视图。当然你执行时可能会遇到如下错误:
ERROR 位于第 2 行:
ORA-01779: 无法修改与非键值保存表对应的列
这是因为新建的表emp1还没有主键的缘故
下面增加一个主键
alter table emp1

add constraint pk_emp1 primary key (empno);
执行之后
在执行前面的语句就能成功。
这里我们总结一下:
在oracle中不存在update from结构,所以遇到需要从另外一个表来更新本表的值的问题的时候,有两种解决的办法:
一种是使用子查询,使用子查询时一定要注意where条件(一般后面接exists子句),除非两个表是一一对应的,否则where条件必不可少,遗漏掉where条件时可能会导致插入大量空值。
另外一种是类视图的更新方法,这也是oracle所独有的。先把对应的数据全部抽取出来,然后更新表一样更新数据,这里需要注意的是,必须保证表的数据唯一型。
参考技术A SQL:贴个以前做过的例子:原理就是用exists
UPDATE MD_MATERIAL S --------------------表名
SET (S.MATERIAL_CODE, S.UOM_CODE) =
(SELECT M.NEW_MATERIAL_CODE, M.NEW_UOM_CODE
FROM MD_MATERIAL_ERP_UPDATE M
WHERE M.OLD_MATERIAL_CODE = S.MATERIAL_CODE)
WHERE EXISTS (SELECT S.ROW_ID
FROM MD_MATERIAL_ERP_UPDATE M --------------------表名
WHERE M.OLD_MATERIAL_CODE = S.MATERIAL_CODE);
外面这层子句exists相当于一个保险。

SQL2:还有一种相当于查询出视图更新的SQL,就是吧要更新的数据都查询进一个视图,再进行UPDATE,这个方法比较绕,我自己也理不清,就不误人子弟了,楼主可自行百度。

FUNCTION/procedure:当然是游标了,查询,判断,update,没什么难度。不废话了。

临时表:其实可以说是SQL2方法的基本原理,先把两个表的数据以ID相等为条件查出来后一起放进一个临时表,临时表包含了两个表的字段,可以A_ID,B_ID这样做列名。再对临时表做UPDATE就跟我么常用的UPDATE方法一样了,update后再把A_*的数据更新进A表就好了。
参考技术B 1、update a,b set a.name=b.name,a.result=b.result,a.remark=b.remark where a.id=b.id;
2、create or replace procedure test() as
begin
update a,b set a.name=b.name,a.result=b.result,a.remark=b.remark where a.id=b.id;
end test;
/
3、shell script
id.txt包含id列表,每行一个id

#!/bin/sh
for id in `cat id.txt`;do
echo -e "update a set a.name=(select z.name from b z where z.id=$id),a.result=(select x.result from b x where x.id='$id'),a.remark=(select y.remark from b y where y.id='$id') where a.id='$id';"
done | sqlplus -s 'user/pw'

以上是关于oracle的表更新问题的主要内容,如果未能解决你的问题,请参考以下文章

Oracle:在更新具有多列的表的一个字段时复制行

如何在Oracle中多次更新与另一个表连接的表?

鉴于oracle中的表结构相同,如何从tableA更新tableB中数据不相同的行?

在更新 cx_oracle 中的表时出现 DatabaseError: ORA-00933: SQL 命令未正确结束

Oracle - 使用 CURSOR LOOP 进行批量更新

在 Oracle 中更新表