Dlaczego chcesz zatwierdzać partiami? To tylko spowolni twoje przetwarzanie. O ile nie istnieją inne sesje, które próbują zmodyfikować wiersze, które próbujesz usunąć, co wydaje się problematyczne z innych powodów, najskuteczniejszym podejściem byłoby po prostu usunięcie danych za pomocą jednego DELETE, tj.
DELETE FROM uiv_response_income uri
WHERE EXISTS(
SELECT 1
FROM (<<bulk_delete_dup query>>) bdd
WHERE bdd.rowid = uri.rowid
)
Oczywiście może istnieć bardziej optymalny sposób pisania tego, w zależności od tego, jak zaprojektowane jest zapytanie za kursorem.
Jeśli naprawdę chcesz wyeliminować BULK COLLECT (co znacznie spowolni proces), możesz użyć składni GDZIE BIEŻĄCY OF, aby wykonać USUŃ
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.
Pamiętaj jednak, że skoro musisz zablokować wiersz (za pomocą klauzuli FOR UPDATE), nie możesz umieścić zatwierdzenia w pętli. Wykonanie zatwierdzenia zwolni blokady, o które prosiłeś za pomocą opcji FOR UPDATE, a otrzymasz komunikat ORA-01002:błąd pobierania poza kolejnością
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
Możesz nie otrzymać błędu w czasie wykonywania, jeśli usuniesz blokadę i unikniesz składni WHERE CURRENT OF, usuwającej dane na podstawie wartości pobranych z kursora. Jednak nadal wykonuje to pobieranie przez zatwierdzenie, co jest kiepską praktyką i radykalnie zwiększa szanse, że przynajmniej sporadycznie otrzymasz błąd ORA-01555:migawka zbyt stara. Będzie również boleśnie powolny w porównaniu z pojedynczą instrukcją SQL lub opcją 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.
Oczywiście musisz również upewnić się, że proces jest możliwy do ponownego uruchomienia na wypadek, gdy przetwarzasz jakiś podzbiór wierszy i masz nieznaną liczbę tymczasowych zatwierdzeń przed śmiercią procesu. Jeśli DELETE
wystarczy, aby wiersz nie był już zwracany z kursora, prawdopodobnie proces jest już możliwy do ponownego uruchomienia. Ale ogólnie jest to problem, jeśli spróbujesz podzielić jedną operację na wiele transakcji.