日期:2014-05-16  浏览次数:20701 次

有大约70万条数据需要更新,用游标的话效率会很低吗?
有一张业务表tmp_stg_serv记录有业务编号serv_id和地址stid等信息,有70多万条数据;另外有一个业务清理表tmp_imp_serv,记录的是手工清理后的业务编号(serv_id)、地址(stid)以及清理时间(imp_date)等信息;还有一张业务历史记录表tmp_hist_serv,记录有业务编号(serv_id)和业务发生了变化的时间(start_date)等信息。

由于不清楚业务清理是发生在业务变动前还是变动后,所以现在需要根据tmp_hist_serv表里最近的start_time来与imp_time作比较以判断业务清理是在前还是在后。如果发现业务清理发生在最新变动的业务之后,那么就要用tmp_imp_serv表里的stid覆盖tmp_stg_serv表的stid,否则就不覆盖。用游标实现过程如下:

declare
v_date date;
cursor cur_servid is
select serv_id from tmp_stg_serv;
v_servid number(10);

begin
open cur_servid;
loop
fetch cur_servid into v_servid;
exit when cur_servid%notfound;

select ta.start_date into v_date from
(select * from tmp_hist_serv
where serv_id=v_servid order by start_date desc) ta
where rownum=1

update tmp_stg_serv ss set (ss.stid,ss.addr_grade,ss.addrid_source)=
(select sa.stid,sa.st_grade,3 from tmp_imp_serv sa
where sa.serv_id=ss.serv_id)
where exists(select 1 from tmp_imp_serv sa
where sa.serv_id=v_servid and (sa.imp_date-v_date)>0) --确定业务变动发生在清理后,更新stid等信息

end loop;
close cur_servid;
end;

不知道用上面的方法实现的话效率会不会很低?大侠们有没有好的改进办法?多谢了!

------解决方案--------------------
游标定位70W 条数据,PGA都占满了吧
------解决方案--------------------
可以考虑用批处理 forall等
------解决方案--------------------
没看,所有update 都可以用update语句搞定
所有insert or update 都可以用merge搞定。
------解决方案--------------------
数据比较多的情况下用游标进行更新的话,速度会很慢而且很占内存。因为游标是把数据全部取出后,然后再逐条处理。
------解决方案--------------------
SQL code
当然要先考虑用SQL直接更新了!
游标太慢了,耗时!