我想使用WITH
子句填充存储过程中的表。我读到的内容是,该子句在会话处于活动状态时会将数据保留在内存中。
有一个表具有我需要更新的信息,称为sprlink,但是该表具有数百万条记录。目前,我的更新如下,但是速度很慢:
open act_rpt_list_cdo;
loop
fetch act_rpt_list_cdo bulk collect into v_act_rpt_list_cdo limit 100;
for i in 1 .. v_act_rpt_list_cdo.count loop
update RPT_LIST_CDO set name_cdo=(select trim(sln.linkvalue) from sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 164 and logidto=0),
date_cdo=(select trim(sln.linkvalue) from sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 165 and logidto=0),
cod_cdo=(select trim(sln.linkvalue) from sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 166 and logidto=0),
log_cdo=(select trim(sln.linkvalue) from sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 167 and logidto=0),
data_cdo=(select trim(sln.linkvalue) from sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 168 and logidto=0)
where rowid=v_act_rpt_list_cdo(i).ri;
end loop;
exit when act_rpt_list_cdo%notfound;
end loop;
close act_rpt_list_cdo
我想在这种情况下使用该子句来限制记录,但是我不知道如何在过程中使用它:
WITH tt_sprlink AS (select sln.objectid as objectid , sln.linkid as linkid, trim(sln.linkvalue) linkvalue
from sprlinks sln join RPT_LIST_CDO rpt on (sln.objectid=rpt.id and sln.logidto=0)
where sln.linkid in (164,165,166,167,168))
select *
from tt_sprlink
由于tt_srplink仅具有更新所需的记录,因此可以通过以下方式进行操作。
act_rpt_list_cdo
loop
fetch act_rpt_list_cdo bulk collect into v_act_rpt_list_cdo limit 100;
for i in 1 .. v_act_rpt_list_cdo.count loop
update RPT_LIST_CDO set name_cdo=(select trim(sln.linkvalue) from tt_sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 164),
date_cdo=(select trim(sln.linkvalue) from tt_sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 165),
cod_cdo=(select trim(sln.linkvalue) from tt_sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 166),
log_cdo=(select trim(sln.linkvalue) from tt_sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 167),
data_cdo=(select trim(sln.linkvalue) from tt_sprlink sln where sln.objectid=v_act_rpt_list_cdo(i).id and SLN.LINKID = 168)
where rowid=v_act_rpt_list_cdo(i).ri;
end loop;
exit when act_rpt_list_cdo%notfound;
end loop;
close act_rpt_list_cdo
有什么建议或想法吗?
答案 0 :(得分:3)
首先:WITH
子句“在会话处于活动状态时保留内存中的数据”的说法是 false 。 WITH cursor_var AS (SELECT ...) LOOP
构造只是一个游标循环-与您获得的OPEN..FETCH..CLOSE
循环相同。就是说:WITH
游标循环有很多让人喜欢的地方,但是神奇的数据缓存并不是其中之一。
第二个:除非您省略了某些内容,否则在这种情况下似乎不需要PL / SQL。正如您所拥有的,逐行游标处理将比单个SQL语句慢得多。 (您的情况更糟,因为您还要为每个更新执行5个标量子查询。)
以下是使用单个UPDATE
语句可以实现目标的方法:
UPDATE rpt_list_cdo u
SET ( name_cdo, date_cdo, cod_cdo, log_cdo, data_cdo ) =
(
SELECT MAX(DECODE(sln.linkid,164,trim(sln.linkvalue),null)) name_cdo,
MAX(DECODE(sln.linkid,165,trim(sln.linkvalue),null)) date_cdo,
MAX(DECODE(sln.linkid,166,trim(sln.linkvalue),null)) cod_cdo,
MAX(DECODE(sln.linkid,167,trim(sln.linkvalue),null)) log_cdo,
MAX(DECODE(sln.linkid,168,trim(sln.linkvalue),null)) data_cdo
FROM sprlinks sln
WHERE sln.objectid = u.id
AND sln.linkid in (164,165,166,167,168))
WHERE 1=1
AND -- whatever other conditions you have in your act_rpt_list_cdo cursor
MERGE
也可以,但是在这种情况下,我更喜欢UPDATE
,因为在act_rpt_list_cdo
光标中添加其他条件会更容易。