爲什麼要批量提交?這隻會降低你的處理速度。除非有試圖修改您要刪除,這似乎是因爲其他原因有問題的行其他場次,最有效的方法是簡單地用一個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做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
足以導致該行不再從光標返回,那麼您的進程可能已經可以重新啓動。但總的來說,如果您嘗試將單個操作分解爲多個事務,則這是一個問題。
我將確保基於集合的解決方案不是試圖去光標的路線前一個選項。基於集合的解決方案將比光標效率更高,代碼更少,更易於理解......請問爲什麼標準刪除在您的方案中不起作用? – 2011-04-22 16:25:36
在我工作的地方有一項政策。沒有單個事務應該運行超過8秒鐘。這就是爲什麼我不能簡單地在一行sql中做到這一點。 – Omnipresent 2011-04-22 17:48:40
因此,這個可疑策略的解決方案是將所有事務拆分爲單行事務,並犧牲數據的一致性? – 2011-04-26 13:05:17