Oracle使用游标从另一表更新不同行列的问题及解决方法
解决Oracle批量更新不同值的问题
嘿,我来帮你搞定这个问题!你的代码现在出现的问题很典型——每次循环里的UPDATE语句没有指定要更新employee_1里的哪一行,所以每次都会把整个表的所有employee_id都改成当前游标取到的值,循环151次后,所有行自然就都变成最后一次取到的那个ID了。
下面给你两种可行的解决方案,优先推荐第二种批量更新的方式,性能会好很多:
方案一:修正游标循环,指定更新行
如果一定要用游标来实现,你需要给employee_1的行做唯一标识(比如用行号或者表本身的主键列),让每次循环只更新对应的那一行。
假设employee_1没有主键,我们可以用伪列rownum来匹配行顺序(注意:rownum是基于查询结果的顺序,如果你需要固定顺序,最好先给employee_1加上自增主键列):
declare -- 提前取employees的前151行,同时带上行号 cursor c1 is select employee_id, rownum as row_num from employees where rownum <= 151; v_emp_id employees.employee_id%type; v_row_num number; Begin open c1; loop fetch c1 into v_emp_id, v_row_num; exit when c1%notfound; -- 游标取完数据就退出 -- 只更新employee_1中对应行号的记录 update employee_1 set employee_id = v_emp_id where rownum = v_row_num; end loop; commit; -- 记得提交更新 close c1; end; /
如果employee_1有自增主键(比如id列,值从1到N),那WHERE条件可以改成where id = v_row_num,这样匹配会更准确,不受表行顺序变化的影响。
方案二:用MERGE批量更新(推荐)
游标逐行更新的性能比较差,尤其是数据量较大的时候。Oracle的MERGE语句可以实现批量匹配更新,效率更高:
merge into employee_1 e1 using ( -- 取出employees前151行,带上行号 select employee_id, rownum as row_num from employees where rownum <= 151 ) e -- 匹配employee_1的行号和子查询的行号 on (e.row_num = (select rownum from employee_1 where rowid = e1.rowid)) when matched then update set e1.employee_id = e.employee_id; commit; -- 提交事务
同样,如果employee_1有自增主键id,ON条件可以简化为on (e.row_num = e1.id),这样逻辑更清晰,也更可靠。
内容的提问来源于stack exchange,提问作者Manu
相关产品推荐
相关产品推荐

