BULK COLLECT を使用して Oracle (11g) でレコードを処理しているときに、興味深い予期しない問題に遭遇しました。
次のコードは問題なく実行され、100 万以上のすべてのレコードを問題なく処理しました。
-- Define cursor
cursor My_Data_Cur Is
Select col1
,col2
from My_Table_1;
…
-- Open the cursor
open My_Data_Cur;
-- Loop through all the records in the cursor
loop
-- Read the first group of records
fetch My_Data_Cur
bulk collect into My_Data_Rec
limit 100;
-- Exit when there are no more records to process
Exit when My_Data_Rec.count = 0;
-- Loop through the records in the group
for idx in 1 .. My_Data_Rec.count
loop
… do work here to populate a records to be inserted into My_Table_2 …
end loop;
-- Insert the records into the second table
forall idx in 1 .. My_Data_Rec.count
insert into My_Table_2…;
-- Delete the records just processed from the source table
forall idx in 1 .. My_Data_Rec.count
delete from My_Table_1 …;
commit;
end loop;
100 レコードの各グループ (上限は 100) の処理の最後に、読み取って処理したばかりのレコードを削除するので、カーソル定義に「for update」構文を追加して、別のプロセスが実行できるようにすることをお勧めします。データが読み取られてからレコードが削除されるまでの間、レコードを更新しないでください。
だから、私が変更した唯一のコードは…</p>
cursor My_Data_Cur
is
select col1
,col2
from My_Table_1
for update;
この変更後に PL/SQL パッケージを実行すると、ジョブは 100 レコードしか処理せずに終了します。カーソルから「for update」を削除することで、この変更が問題の原因であることを確認し、もう一度パッケージがソース テーブルのすべてのレコードを処理しました。
「for update」句を追加すると、この動作が変化する理由はありますか? この問題を回避する方法について何か提案はありますか? プロセスの開始時にテーブルで排他的トランザクションを開始しようとしていますが、データを処理するテーブル全体をロックしたくないため、これは解決策ではありません。
よろしくお願いいたします。
許す