我制作了一个游标,以便合并/更新数据库中的记录
我想知道它是否正确或是否有任何建议,以改善查询.
DECLARE
CURSOR c_itemloc
IS
SELECT
item ,
loc ,
loc_type ,
source_method ,
primary_supp ,
source_wh
FROM
(SELECT dc_vert.item ,
dc_vert.loc ,
dc_vert.loc_type ,
dc_vert.source_method ,
dc_vert.primary_supp ,
w.primary_vwh source_wh --,dc_vert.source_wh
,
dc_vert.actie ,
MAX(dc_vert.actie) over (PARTITION BY dc_vert.item, dc_vert.loc) actie_max ,
COUNT(dc_vert.primary_supp) over (PARTITION BY dc_vert.item, dc_vert.loc) primary_count
FROM dc_item_loc_pim_lms dc_vert ,
item_supplier isu ,
store sto ,
wh w
WHERE dc_vert.primary_supp IS NOT NULL
AND isu.item = dc_vert.item
AND dc_vert.primary_supp = isu.supplier
AND W.WH = dc_vert.source_wh
AND sto.store = dc_vert.loc
AND ISU.SUPP_DISCONTINUE_DATE >= SYSDATE
)
WHERE actie = actie_max
AND primary_count = 1;
l_item item_loc.item%TYPE;
l_loc item_loc.loc%TYPE;
loc_type item_loc.loc_type%TYPE;
l_source_method item_loc.source_method%TYPE;
l_primary_supp item_loc.primary_supp%TYPE;
l_source_wh item_loc.source_wh%TYPE;
i NUMBER;
l_commit VARCHAR2(1) := 'Y';
BEGIN
i :=0;
FOR r_itemloc IN c_itemloc
LOOP
i := i+1;
UPDATE item_loc il
SET
il.source_method = r_itemloc.source_method , -- 'S'
il.loc_type = r_itemloc.loc_type , -- 'S'
il.primary_supp = r_itemloc.primary_supp ,
il.source_wh = r_itemloc.source_wh ,
il.last_update_datetime = SYSDATE
WHERE item = r_itemloc.item
AND loc = r_itemloc.loc;
IF l_commit = 'Y' AND mod(i, 1000) = 0 THEN
COMMIT ;
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('SOMETHING WENT WRONG');
END;
Run Code Online (Sandbox Code Playgroud)
假设代码在功能上符合您的要求......
1)删除异常处理程序.捕获一个你无法处理的未知异常没有任何好处,除非你正在做一些事情,比如记录它并重新抛出它.仅仅为了调用dbms_output
而捕获异常不仅会隐藏异常详细信息以及调试异常所需的堆栈跟踪,如果调用者没有从缓冲区dbms_output
写入读取,它可能会完全隐藏异常.
2)循环中的提交通常是个坏主意.最重要的是,如果你的会话在中间死亡会发生什么?您有一个部分提交的更新,以后在以后重新启动代码时无法恢复操作.您必须重新更新之前更新的所有行以及您提交的可能具有下游影响的更新.并且在循环中提交会减慢代码的速度,这是没有实际意义的.
3)如果您要做的只是更新表,最有效的方法是编写一个UPDATE
语句,一次更新所有行,而不是迭代游标并执行大量单行更新.可能有其他理由支持游标(例如,它可能使代码更容易让其他开发人员理解),但从性能角度来看,如果你可以在SQL中完成,SQL将是最有效的方法.