update更新多行数据(oracle)
转自:http://blog.itpub.net/25322446/viewspace-767505
说明:笔记总结了在工作中遇到过的几种update方法和各种方法适用的范围。
1.单表更新
方案:使用标准update语法即可,执行稳定且效率较高
update table set (column1,column2,...)= value1,value2,... ;
2.多表关联更新
举例:更新gkfq_rec表中所有slid与oa2_ftask表fi_inst相同的行,blzt字段值=oa2_ftask表的ft_lstate。
create table gkfq_rec ( slid char(12) parimary key, blzt varchar2(50), wjbt varchar2(100) not null, ........ ); create table oa2_ftask ( fi_inst char(12) parimary key, fi_state int not null, ft_lstate int not null, ... );
方法描述 |
适用范围 |
运行效率 |
传统方案 | 一般情况适用 | 单表更新效率高且稳定,多表时效率较慢 |
inline view更新法 | 关联字段为主键 | 速度较快 |
merge更新法 | 关联字段非主键,适用于两表关联 | 非主键关联表更新,速度较快 |
快速游标更新法 | 逻辑较复杂的情况 | 复杂逻辑时效率很高 |
(1)传统方案(速度可能最慢)
update gkfq_rec a set blzt= (select b.ft_lstate from oa2_ftask b where a.slid=b.fi_inst) where exists (select 1 from oa2_ftask b where a.slid=b.fi_inst) ;
//子查询返回多行值时,通过where exists条件逐行过滤,一一匹配实现set唯一值
(2)inline view更新法(关联主键字段,速度较快)
方案:更新一个临时建立的视图。要求B表的主键字段必须在where条件中,并且是以=号来关联被更新表,否则可能报错:ORA-01779:无法修改与非键值保存表对应的列。当B表主键字段为多列组合时,也有可能出现这一报错。
update (select a.blzt as blzt,b.ft_lstate as ft_lstate from gkfq_rec a,oa2_ftask b where a.slid=b.fi_inst) set blzt=ft_lstate ;
(3)merge更新法(关联字段非主键时,速度较快)
语法:
MERGE INTO table_name alias 1 USING (table|view|sub_query) alias 2 ON (join condition) WHEN MATCHED THEN UPDATE SET col1=col_val1, col2=col_val2 WHEN NOT MATCHED THEN INSERT (column_list) VALUES (column_values);
方案:在alias2中select出来的数据,每一条都跟alias1进行ON (join condition)比较,若匹配,就进行更新操作,不匹配,执行插入操作。merge不会返回影响行数,且最多只能两表关联,适用于连接条件不是主键的字段。
merge into gkfq_rec a using oa2_ftask b on (a.slid=b.fi_inst) when matched then update set a.blzt=b.ft_lstate;
(4)快速游标更新法(复杂逻辑时,效率很高)
语法:
begin for cr in (查询语句) loop --循环 update table_name set ... --更新语句(根据查询出来的结果集合) end loop; --结束循环 end;
方案:配合oracle独有的内置ROWID物理字段,使用快速游标,不需要定义,直接把游标写到for循环中,快速定位并执行更新。它可以支持复杂逻辑的查询语句,更新准确,无论数据多大更新效率依然很高。但执行后不返回影响行数。
begin for aa in (select a.rowid as rowid,b.ft_lstate as ft_lstate from gkfq_rec a,oa2_ftask b where a.slid=b.fi_inst ) loop update gkfq_rec set blzt=aa.ft_lstate where rowid=aa.rowid; end loop; end;