3

次のような一括挿入操作からエラーをキャッチしています。

begin
    --bulk insert
    forall i in v_data.first .. v_data.last save exceptions
        insert into my_filter_table values v_data (i);

    commit;

exception
    -- catch and print the saved-up DML errors.
    when X_DML_ERRORS then
        declare
            v_iteration number;
        begin
            dbms_output.put_line('');
            dbms_output.put_line('DML Errors:');
            for i in 1 .. SQL%BULK_EXCEPTIONS.count loop
                v_iteration := SQL%BULK_EXCEPTIONS(i).error_index;

                dbms_output.put_line('Iteration: '||v_iteration||' Message: '||
                                 SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));


            end loop;
        end;
end;

出力は次のようになります。

    反復: 3 メッセージ: ORA-01400: () に NULL を挿入できません
    反復: 4 メッセージ: ORA-02290: チェック制約 (.) 違反
    繰り返し: 8 メッセージ: ORA-00001: 一意の制約 (.) に違反しています

エラー処理コードをテストしているので、エラーが発生しても問題ありません。問題は、Oracle のエラー メッセージに制約名が表示されないことです。つまり、表示されますcheck constraint (.) violatedが、違反したチェック制約がわかりません。

これで何が起こっているのか誰か知っていますか?

(Oracle バージョン 10.2)

4

1 に答える 1

6

SQL%BULK_EXCEPTIONS(i).error_codeは、Oracleエラー番号のみを保存します。次に、sqlerrm関数を使用してエラーメッセージテキストを検索します。その関数には、どの制約が破られているかを知る方法がありません。

結果を複製するために例外がスローされることなく、sqlerrm関数を呼び出すことができます。

begin
   dbms_output.put_Line(sqlerrm(-1400));
   dbms_output.put_Line(sqlerrm(-2290));
   dbms_output.put_Line(sqlerrm(-1));
end;

どの出力

ORA-01400: cannot insert NULL into ()
ORA-02290: check constraint (.) violated
ORA-00001: unique constraint (.) violated

考えられる回避策は、例外ハンドラで失敗したステートメントを再実行することです。

テーブル定義:

create table t ( x number(1) primary key);

コード:

declare
   dml_errors EXCEPTION;
   PRAGMA EXCEPTION_INIT(dml_errors, -24381);
   TYPE t_nums is table of NUMBER;
   l_nums t_nums := t_nums(1,1,10);
begin
   forall i in 1..l_nums.count save exceptions
      execute immediate 'insert into t values (:x)' using l_nums(i);
exception
   when dml_errors then
      for j in 1..sql%bulk_exceptions.count
      loop
         if sql%bulk_exceptions(j).error_code = 1
         then
            begin
               execute immediate 'insert into t values (:x)'
                  using l_nums(sql%bulk_exceptions(j).error_index);
            exception
               when dup_val_on_index then
                  dbms_output.put_line(sqlerrm);
            end;
         else
            dbms_output.put_line(sqlerrm(-sql%bulk_exceptions(j).error_code));
         end if;
      end loop;
end;

どの出力:

ORA-01438: value larger than specified precision allowed for this column
ORA-00001: unique constraint (XXXXXXXX.SYS_C00264470) violated
ORA-24381: error(s) in array DML
于 2010-01-27T18:39:26.683 に答える