Почему вы хотите совершать партии?Это только замедлит вашу обработку.Если нет других сеансов, которые пытаются изменить строки, которые вы пытаетесь удалить, что кажется проблематичным по другим причинам, наиболее эффективным подходом было бы просто удалить данные с помощью одного DELETE, то есть
DELETE FROM uiv_response_income uri
WHERE EXISTS(
SELECT 1
FROM (<<bulk_delete_dup query>>) bdd
WHERE bdd.rowid = uri.rowid
)
Конечно, вполне может быть более оптимальный способ написать это в зависимости от того, как устроен запрос за вашим курсором.
Если вы действительно хотите исключить BULK COLLECT (который существенно замедлит процесс)вы можете использовать синтаксис WHERE CURRENT OF для выполнения 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.
Однако учтите, что, поскольку вам нужно заблокировать строку (с помощью предложения FOR UPDATE), вы не можете поместить коммит впетля.Выполнение фиксации приведет к снятию блокировок, запрошенных вами с помощью FOR UPDATE, и вы получите ORA-01002: ошибка выборки из последовательности
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
Вы можете не получить ошибку времени выполнения, если уберете блокировкуи избегайте синтаксиса WHERE CURRENT OF, удаляя данные на основе значений, выбранных вами из курсора.Однако, это все еще делает выборку через фиксацию, что является плохой практикой и радикально увеличивает шансы, что вы, по крайней мере периодически, получите ошибку ORA-01555: снимок слишком старый.Он также будет мучительно медленным по сравнению с одним оператором SQL или параметром 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.
Конечно, вы также должны убедиться, что ваш процесс перезапускается, если вы обрабатываете некоторое подмножество строк и имеетекакое-то неизвестное количество временных коммитов до того, как процесс умирает.Если DELETE
достаточно, чтобы строка больше не возвращалась из вашего курсора, ваш процесс, вероятно, уже перезапускается.Но в целом это вызывает беспокойство, если вы пытаетесь разбить одну операцию на несколько транзакций.