Hvorfor vil du binde dig i batches? Det vil kun sinke din behandling. Medmindre der er andre sessioner, der forsøger at ændre de rækker, du forsøger at slette, hvilket virker problematisk af andre årsager, ville den mest effektive tilgang blot være at slette dataene med en enkelt DELETE, dvs.
DELETE FROM uiv_response_income uri
WHERE EXISTS(
SELECT 1
FROM (<<bulk_delete_dup query>>) bdd
WHERE bdd.rowid = uri.rowid
)
Selvfølgelig kan der være en mere optimal måde at skrive dette på afhængigt af hvordan forespørgslen bag din markør er designet.
Hvis du virkelig ønsker at eliminere BULK COLLECT (hvilket vil bremse processen betydeligt), kan du bruge WHERE CURRENT OF-syntaksen til at udføre 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.
Vær dog opmærksom på, at da du skal låse rækken (med FOR UPDATE-klausulen), kan du ikke sætte en commit i løkken. Hvis du foretager en commit, frigives de låse, du havde anmodet om med FOR UPDATE, og du vil få en ORA-01002:hent ud af sekvensfejl
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
Du får muligvis ikke en runtime-fejl, hvis du fjerner låsningen og undgår WHERE CURRENT OF-syntaksen, og sletter data baseret på den eller de værdier, du hentede fra markøren. Dette er dog stadig en hentning på tværs af commit, hvilket er en dårlig praksis og radikalt øger oddsene for, at du, i det mindste med mellemrum, vil få en ORA-01555:snapshot for gammel fejl. Det vil også være smerteligt langsomt sammenlignet med den enkelte SQL-sætning eller BULK COLLECT-indstillingen.
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.
Selvfølgelig skal du også sikre dig, at din proces kan genstartes, hvis du behandler nogle undersæt af rækker og har et ukendt antal midlertidige commits, før processen dør. Hvis DELETE
er tilstrækkeligt til at forårsage, at rækken ikke længere returneres fra din markør, kan din proces sandsynligvis allerede genstartes. Men generelt er det en bekymring, hvis du forsøger at opdele en enkelt operation i flere transaktioner.