Proč se chcete zavázat v dávkách? To jen zpomalí vaše zpracování. Pokud neexistují jiné relace, které se pokoušejí upravit řádky, které se pokoušíte odstranit, což se zdá problematické z jiných důvodů, nejúčinnějším přístupem by bylo jednoduše smazat data pomocí jediného DELETE, tj.
DELETE FROM uiv_response_income uri
WHERE EXISTS(
SELECT 1
FROM (<<bulk_delete_dup query>>) bdd
WHERE bdd.rowid = uri.rowid
)
Samozřejmě může existovat optimálnější způsob zápisu v závislosti na tom, jak je navržen dotaz za kurzorem.
Pokud opravdu chcete odstranit BULK COLLECT (což proces podstatně zpomalí), můžete použít syntaxi WHERE CURRENT OF k provedení DELETE
SQL> create table foo
2 as
3 select level col1
4 from dual
5 connect by level < 10000;
Table created.
SQL> ed
Wrote file afiedt.buf
1 declare
2 cursor c1 is select * from foo for update;
3 l_rowtype c1%rowtype;
4 begin
5 open c1;
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.
Uvědomte si však, že protože musíte zamknout řádek (klauzulí FOR UPDATE), nemůžete do smyčky vložit potvrzení. Provedení odevzdání by uvolnilo zámky, které jste požadovali pomocí FOR UPDATE, a dostanete chybu ORA-01002:fetch out of sequence
SQL> ed
Wrote file afiedt.buf
1 declare
2 cursor c1 is select * from foo for update;
3 l_rowtype c1%rowtype;
4 begin
5 open c1;
6 loop
7 fetch c1 into l_rowtype;
8 exit when c1%notfound;
9 delete from foo where current of c1;
10 commit;
11 end loop;
12* end;
SQL> /
declare
*
ERROR at line 1:
ORA-01002: fetch out of sequence
ORA-06512: at line 7
Pokud odstraníte zamykání a vyhnete se syntaxi WHERE CURRENT OF, smažete data na základě hodnot, které jste načetli z kurzoru, nemusí se zobrazit chyba za běhu. Stále však dochází k načítání přes commit, což je špatný postup a radikálně zvyšuje pravděpodobnost, že alespoň občas dostanete chybu ORA-01555:snímek je příliš starý. Bude to také bolestně pomalé ve srovnání s jedním příkazem SQL nebo možností BULK COLLECT.
SQL> ed
Wrote file afiedt.buf
1 declare
2 cursor c1 is select * from foo;
3 l_rowtype c1%rowtype;
4 begin
5 open c1;
6 loop
7 fetch c1 into l_rowtype;
8 exit when c1%notfound;
9 delete from foo where col1 = l_rowtype.col1;
10 commit;
11 end loop;
12* end;
SQL> /
PL/SQL procedure successfully completed.
Samozřejmě musíte také zajistit, aby byl váš proces restartovatelný v případě, že zpracováváte nějakou podmnožinu řádků a máte nějaký neznámý počet prozatímních potvrzení, než proces skončí. Pokud DELETE
stačí k tomu, aby se řádek již nevracel z vašeho kurzoru, váš proces je pravděpodobně již restartovatelný. Ale obecně to znepokojuje, pokud se pokoušíte rozdělit jednu operaci na více transakcí.