回答

收藏

如何从游标中获取、删除、提交

技术问答 技术问答 172 人阅读 | 0 人回复 | 2023-09-14

我试着从表中删除很多行。我想尝试将要删除的行放入游标中,然后继续获取、删除和提交游标的每一行,直到它是空的。
. M9 X, x7 F$ w5 }1 L* T. u/ J在下面的代码中,我们是fetching把它放进去TYPE。* ^- }6 m0 b( x$ Q" _+ I
如何从图片中修改以下代码并删除?TYPE,只是简单fetch,delete,commit操作光标本身。
4 d  @8 C: p7 K: ^9 h                OPEN bulk_delete_dup;    LOOP        FETCH bulk_delete_dup BULK COLLECT INTO arr_inc_del LIMIT c_rows;        FORALL i IN arr_inc_del.FIRST .. arr_inc_del.LAST              DELETE FROM UIV_RESPONSE_INCOME               WHERE ROWID = arr_inc_del(i);        COMMIT;        arr_inc_del.DELETE;        EXIT WHEN bulk_delete_dup%NOTFOUND;    END LOOP;    arr_inc_del.DELETE;    CLOSE bulk_delete_dup;               
0 e0 j3 ?0 D. Z/ g    解决方案:                                                               
$ b, Z$ D% o' X( R( i) Y) v                                                                为什么要分批提交?这只会减慢你的处理速度。除非有其他会话试图修改要删除的行,否则由于其他原因,这似乎是一个问题。最有效的方法是简单地使用一个DELETE删除数据,即
' |+ m. {! z3 t! l5 O1 i9 HDELETE FROM uiv_response_income uri WHERE EXISTS(     SELECT 1       FROM () bdd     WHERE bdd.rowid = uri.rowid  )当然,根据游标后面查询的设计方法,可能会有更理想的写作方法。
6 U& D  {& ~4 |# o# |: v如果你真的想消除批量收集(这将大大减缓这个过程),你可以使用 WHERE CURRENT OF删除语法% K4 _- d8 F% ~0 V4 D
SQL> create table foo  2  as  3  select level col1  4    from dual  5  connect by level  edWrote file afiedt.buf  1  declare 2     cursor c1 is select * from foo for update; 3     l_rowtype c1%rowtype;  4  begin 5     open c一、 6     loop  7       fetch c1 into l_rowtype; 8        exit when c1%notfound; 9        delete from foo where current of c1; 10    end loop; 11* end;SQL> /PL/SQL procedure successfully completed.但请注意,必须锁定行(使用)FOR UPDATE因此,提交不能放入循环中。提交将释放您的使用FOR
9 t  r+ I; n! E( e. iUPDATE要求的锁,你会得到的ORA-01002:提取顺序错误/ k1 \& ~( X; u; [2 h
SQL> edWrote file afiedt.buf  1  declare 2     cursor c1 is select * from foo for update; 3     l_rowtype c1%rowtype;  4  begin 5     open c一、 6     loop  7      fetch c1 into l_rowtype; 8        exit when c1%notfound; 9        delete from foo where current of c1;1;10;10;     commit; 11    end loop; 12* end;SQL> /declare*ERROR at line 1:ORA-01002: fetch out of sequenceORA-06512: at line 7删除锁并避免使用WHERE CURRENT% T. K) f: J/ I! j% m7 `! C% H% d
OF语法,但根据从游标中获得的值删除数据,在运行过程中可能不会收到错误。然而,这仍然是跨提交阅读,这是一个糟糕的做法,并从根本上增加你至少间歇性地获得ORA-01555:快照过旧的错误概率。SQL语句或BULK+ c1 m$ T" O& e2 L8 c; U4 K. c6 \, ~
COLLECT与选项相比,它也会很慢。
% A- _* [3 Z0 {4 mSQL> edWrote file afiedt.buf  1  declare 2     cursor c1 is select * from foo; 3     l_rowtype c1%rowtype;  4  begin 5     open c一、 6     loop  7       fetch c1 into l_rowtype; 8        exit when c1%notfound; 9        delete from foo where col1 = l_rowtype.col1;1;10;10;     commit; 11    end loop; 12* end;SQL> /PL/SQL procedure successfully completed.当然,您还必须确保您的流程可以重新启动,以防止您在流程终止前临时提交一些未知的子集。DELETE如果你不再从游标返回银行,你的过程可能已经重新开始。但总的来说,如果你试图将单个操作分解为多个事务,你需要担心。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则