2016-08-18 11 views
2

テーブルに挿入する行は10.000です。私は非型付き表でそれらの項目を挿入するためにconstrainstの表による違反に挿入doesntの行からデータを回復するにはどうすればよいoracleに挿入してFORALLについては挿入されていない行を修復するOracle

...

FORALL x IN TABLE_NAME.First .. TABLE_NAME.Last 
    INSERT 
    INTO TABLE_NAME VALUES 
    (
     TABLE_NAME(x).VAL1, 
     TABLE_NAME(x).VAL2, 
     TABLE_NAME(x).VAL3, 
     TABLE_NAME(x).VAL4, 
     TABLE_NAME(x).VAL5 
    ); 

拒否されたアイテムの

答えて

4

save exceptions clause of the forall statementを使用してエラーを収集し、the sql%bulk_exceptions implicit cursor attributeを使用して実際に何が起こったかを確認できます。そこそのドキュメントにan exampleだが、あなたのケースであなたは(作っテーブルとデータを使用)を行うことができます:出力を生成

create table your_table (val1 number primary key, val2 number, val3 number, val4 number, val5 number); 

declare 
    type l_table_type is table of your_table%rowtype; 
    l_table l_table_type := l_table_type(); 

    dml_errors exception; 
    pragma exception_init(dml_errors, -24381); 
begin 
    l_table.extend; 
    l_table(l_table.count).val1 := 1; 
    l_table(l_table.count).val2 := 1.2; 
    l_table(l_table.count).val3 := 1.3; 
    l_table(l_table.count).val4 := 1.4; 
    l_table(l_table.count).val5 := 1.5; 

    l_table.extend; 
    l_table(l_table.count).val1 := 2; 
    l_table(l_table.count).val2 := 2.2; 
    l_table(l_table.count).val3 := 2.3; 
    l_table(l_table.count).val4 := 2.4; 
    l_table(l_table.count).val5 := 2.5; 

    l_table.extend; 
    l_table(l_table.count).val1 := 1; 
    l_table(l_table.count).val2 := 3.2; 
    l_table(l_table.count).val3 := 3.3; 
    l_table(l_table.count).val4 := 3.4; 
    l_table(l_table.count).val5 := 3.5; 

    forall x in l_table.first .. l_table.last save exceptions 
    insert 
    into your_table values 
     (
     l_table(x).val1, 
     l_table(x).val2, 
     l_table(x).val3, 
     l_table(x).val4, 
     l_table(x).val5 
    ); 

exception 
    when dml_errors then 
    for i in 1..sql%bulk_exceptions.count loop 
     dbms_output.put_line('Index ' || sql%bulk_exceptions(i).error_index 
     || ' error ' || -sql%bulk_exceptions(i).error_code); 
     dbms_output.put_line(' val1: ' || l_table(sql%bulk_exceptions(i).error_index).val1); 
     dbms_output.put_line(' val2: ' || l_table(sql%bulk_exceptions(i).error_index).val2); 
     dbms_output.put_line(' val3: ' || l_table(sql%bulk_exceptions(i).error_index).val3); 
     dbms_output.put_line(' val4: ' || l_table(sql%bulk_exceptions(i).error_index).val4); 
     dbms_output.put_line(' val5: ' || l_table(sql%bulk_exceptions(i).error_index).val5); 
    end loop; 
end; 
/

を:

PL/SQL procedure successfully completed. 

Index 3 error -1 
val1: 1 
val2: 3.2 
val3: 3.3 
val4: 3.4 
val5: 3.5 

val1セットにして最初のコレクション要素1つは正常に挿入されました。 2つ目はユニーク制約例外を受け取りましたが、そうではありませんでしたが、ステートメント全体が失敗する代わりにバルク例外メカニズムに入れられました。

これで、例外を発生させるか(再発生するか)、即座に(セーブポイントに)ロールバックするかを決めることができます。またはエラーが発生していない挿入をコミットします。

拒否されたアイテムのテーブルに同じ値を挿入することもできますが、他の変更をロールバックする場合は注意が必要です(おそらくそのシナリオにはないと思われます)。

あなたが直接それを行うに別のforallを使用することはできません - values()句内l_table(sql%bulk_exceptions(i).error_index).val1に言及があるため%文字のORA-00911スロー - あなたはforループ内の個々の挿入を行う必要があるだろうか、コピーその値を別のコレクションに追加し、それを一括挿入します。多くの拒絶反応が予想されない限り、個々のインサートは十分かもしれません。

関連する問題