【发布时间】:2017-01-04 02:13:55
【问题描述】:
我有一个 Oracle 程序正在更新低于 10,000 条记录。如果我运行正常的 SQL 语句,它会在几秒(30)内立即返回结果。 程序循环中的相同语句将无限循环。
我的循环语句如下。 注意:data FIELD 数据类型是 clob 而不是 varchar2。
声明:
select
'LB_COPY_CHANGE-'||8 LAST_MODIFIED_BY,
rec.COR_ID_old,
rec.COR_ID_NEW,
replace(replace(replace(a.data,'''id'':'||rec.COR_ID_OLD||',','''id'':'||rec.COR_ID_NEW||','),''id':'||rec.COR_ID_OLD||',',''id':'||rec.COR_ID_NEW||','),'''id'':'||rec.COR_ID_OLD||',','''id'':'||rec.COR_ID_NEW||',') as data
from KPI_MET_FIELD_DATA a, CUSTOM_TEMP_TABLE_SESSION_1 rec
where A.cmf_fk_id in (145,146,147)
and TYPE_LB in (14,15,16)
and a.KDB_FK_ID in (
select distinct km.KDB_FK_ID
from KPI_MET_FIELD_DATA km , KPI_DET_BASE kp, KPI_REL_KPI_SCORECARD ksc, STR_DET_EMP_SCORECARD sc
where ksc.SDE_FK_ID=sc.SDE_PK_ID
and km.KDB_FK_ID = ksc.KDB_KPI_FK_ID
and km.is_deleted=0
and kp.kdb_pk_id = km.KDB_FK_ID
and kp.is_deleted=0
and km.cmf_fk_id in (145,146,147)
and sc.sdp_fk_id = 8)
and a.is_deleted=0
and (a.data like '%'||rec.COR_ID_OLD||'%');
FOR rec in (SELECT * FROM CUSTOM_TEMP_TABLE_SESSION where TYPE_LB in (14,15,16)) LOOP
update KPI_MET_FIELD_DATA
set LAST_MODIFIED_BY='LB_COPY_CHANGE-'||p2 ,
data = replace(replace(replace(data,'''id'':'||rec.COR_ID_OLD||',','''id'':'||rec.COR_ID_NEW||','),''id':'||rec.COR_ID_OLD||',',''id':'||rec.COR_ID_NEW||','),'''id'':'||rec.COR_ID_OLD||',','''id'':'||rec.COR_ID_NEW||',')
where cmf_fk_id in (145,146,147)
and KDB_FK_ID in (
select distinct km.KDB_FK_ID
from KPI_MET_FIELD_DATA km , KPI_DET_BASE kp, KPI_REL_KPI_SCORECARD ksc, STR_DET_EMP_SCORECARD sc
where ksc.SDE_FK_ID=sc.SDE_PK_ID
and km.KDB_FK_ID = ksc.KDB_KPI_FK_ID
and km.is_deleted=0
and kp.kdb_pk_id = km.KDB_FK_ID
and kp.is_deleted=0
and km.cmf_fk_id in (145,146,147)
and sc.sdp_fk_id = p2)
and is_deleted=0 ;
【问题讨论】:
-
你是什么意思,“正常的 SQL 语句?”如果不提供更多细节,比如解释计划,可能有很多可能的原因。需要更多细节。为什么你甚至需要一个循环?
-
相同结果集的选择语句:
-
是否有任何理由在循环中多次更新相同的记录?在 WHERE 语句中,您拥有在 LOOP 语句期间未更改的过滤器。这意味着您一次又一次地更新同一条记录
-
选择不同于更新,它做了两件非常不同的事情。对更新运行解释计划。
-
在 FOR 循环的更新中,您缺少一个 where 过滤器行“和 (a.data like '%'||rec.COR_ID_OLD||'%')”,这会导致更新运行FOR LOOP 游标返回的每条记录。因此 UPDATE 使用 FOR LOOP 光标进行笛卡尔积,而在 select 中两者之间有一个 JOIN。