我试着从表中删除很多行。我想尝试将要删除的行放入游标中,然后继续获取、删除和提交游标的每一行,直到它是空的。 . 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如果你不再从游标返回银行,你的过程可能已经重新开始。但总的来说,如果你试图将单个操作分解为多个事务,你需要担心。