1

主キーのない一時テーブル(約760k行)があります。一括収集とforall(拒否された行をキャッチするために例外の保存も使用)を使用して、この一時テーブルからメインテーブルに行を挿入しようとしていますが、これは正常に実行されました。しかし、拒否されて正常に移動された行を追跡する必要があります(私がやりたいのは、一時テーブルのステータス列をエラーの場合は「E」、正常な移行の場合はMとして更新することです)ここに私の手順があります:

コードスニペット

desc temp_table:
col1 varchar2(30);
col2 varchar2(30);
col3 number;
col4 number;
status varchar2(1);

create or replace procedure mov_to_main_table
as
loop_count number default 0;
error_row_no number default 0;
sql_stmt varchar2(500);
cursor c_data is
   select * from temp_table,a
    where temp_table.col1=a.col;

TYPE t_bulk_collect_tab IS TABLE OF c_data%ROWTYPE;

l_tab t_bulk_collect_tab;
l_inserted t_bulk_collect_tab; 

BEGIN

OPEN c_data;
LOOP
FETCH c_data
BULK COLLECT INTO l_tab LIMIT 1000;

EXIT WHEN l_tab.count = 0;
BEGIN

FORALL i IN 1..l_tab.count  save exceptions
insert into main_table(col1,col2,col3)
values(l_tab(i).col1,l_tab(i).col2,l_tab(i),col3);

EXCEPTION
when others then
bulk_error_count := sql%bulk_exceptions.count;
--dbms_output.put_line('number of error rows :'||bulk_error_count );
for i in 1..bulk_error_count
loop
error_row_no := to_number(SQL%BULK_EXCEPTIONS(i).ERROR_INDEX)+100*loop_count;
sql_stmt := 'update  temp_table set status=''E'' where rowid in (select rowid from     temp_table where rownum <=:1 minus select rowid from temp_table where rownum<:2)';
execute immediate sql_stmt using error_row_no,error_row_no;

end loop;


end;

上記のコードでは、例外部分に入った行を「E」として更新していますが、正常に挿入されている行の場合、ステータスを更新できません。主に、そのrownumまたはrowidをキャッチして、どのiamから取得できないかを更新する必要があります。正常に移動された行を更新するすべての方法については?よろしくお願いします。

4

1 に答える 1

2

あなたのアプローチは非常に賢いですが、正しく機能しないことがいくつかあります。

  1. まず、ここでは動的SQLは必要ありません。すぐに実行する、ドロップしてください。
  2. 例外ブロック内のネストされたテーブルには引き続きアクセスできるため、関連するまたはl_tabを簡単に選択できます。idrowid
  3. 最後に、これはOracleでのページングクエリの使用方法ではありません。SOの例を参照してください。

私のアドバイスは、残りのデータと同時にROWIDをフェッチすることです。

CURSOR c_data IS
   SELECT temp_table.*, a.*, temp_table.rowid rid 
     FROM temp_table, a 
    WHERE temp_table.col1 = a.col;

次に、例外ブロックで、問題のある行を見つけて更新できます。

EXCEPTION
   WHEN OTHERS THEN
      bulk_error_count := SQL%bulk_exceptions.count;
      --dbms_output.put_line('number of error rows :'||bulk_error_count );
      FOR i IN 1 .. bulk_error_count LOOP
         UPDATE temp_table
            SET status = 'E'
          WHERE rowid = l_tab(SQL%BULK_EXCEPTIONS(i).error_index).rid);  
      END LOOP;
END;
于 2013-03-27T12:06:03.050 に答える