Tại sao bạn muốn cam kết theo lô? Điều đó sẽ chỉ làm chậm quá trình xử lý của bạn. Trừ khi có các phiên khác đang cố gắng sửa đổi các hàng mà bạn đang cố xóa, điều này có vẻ có vấn đề vì các lý do khác, cách tiếp cận hiệu quả nhất sẽ chỉ đơn giản là xóa dữ liệu bằng một lần XÓA, tức là
DELETE FROM uiv_response_income uri
WHERE EXISTS(
SELECT 1
FROM (<<bulk_delete_dup query>>) bdd
WHERE bdd.rowid = uri.rowid
)
Tất nhiên, có thể có một cách tối ưu hơn để viết điều này tùy thuộc vào cách truy vấn phía sau con trỏ của bạn được thiết kế.
Nếu bạn thực sự muốn loại bỏ BULK COLLECT (sẽ làm chậm quá trình về cơ bản), bạn có thể sử dụng cú pháp WHERE CURRENT OF để thực hiện XÓA
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.
Tuy nhiên, hãy lưu ý rằng vì bạn phải khóa hàng (với mệnh đề FOR UPDATE), bạn không thể đặt một cam kết trong vòng lặp. Thực hiện một cam kết sẽ giải phóng các khóa bạn đã yêu cầu với FOR UPDATE và bạn sẽ nhận được ORA-01002:lỗi tìm nạp ngoài trình tự
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
Bạn có thể không gặp lỗi thời gian chạy nếu bạn loại bỏ khóa và tránh cú pháp WHERE CURRENT OF, xóa dữ liệu dựa trên (các) giá trị bạn đã tìm nạp từ con trỏ. Tuy nhiên, điều này vẫn đang thực hiện tìm nạp qua cam kết, đây là một thực tiễn kém và làm tăng hoàn toàn khả năng bạn sẽ, ít nhất là không liên tục, nhận được ORA-01555:lỗi snapshot quá cũ. Nó cũng sẽ rất chậm so với câu lệnh SQL đơn hoặc tùy chọn 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.
Tất nhiên, bạn cũng phải đảm bảo rằng quy trình của bạn có thể khởi động lại trong trường hợp bạn xử lý một số tập hợp con của các hàng và có một số cam kết tạm thời không xác định trước khi quy trình chết. Nếu DELETE
là đủ để khiến hàng không còn được trả lại từ con trỏ của bạn nữa, quá trình của bạn có thể đã có thể khởi động lại. Nhưng nói chung, đó là một mối quan tâm nếu bạn cố gắng chia một thao tác thành nhiều giao dịch.