В ошибках Oracle DML отсутствуют детали - PullRequest
3 голосов
/ 27 января 2010

Я получаю сообщения об ошибках от операции массовой вставки, например:

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;

Вывод выглядит примерно так:

    Iteration: 3 Message: ORA-01400: cannot insert NULL into ()
    Iteration: 4 Message: ORA-02290: check constraint (.) violated
    Iteration: 8 Message: ORA-00001: unique constraint (.) violated

То, что я получаю ошибки, меня не беспокоит, так как я тестирую код обработки ошибок. Проблема в том, что в сообщении об ошибке Oracle не отображаются имена ограничений, т. Е. Отображается check constraint (.) violated, но это не говорит мне, ЧТО проверочное ограничение я нарушил.

Кто-нибудь знает, что с этим?

(версия Oracle 10.2)

1 Ответ

6 голосов
/ 27 января 2010

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

Возможным обходным решением будет повторное выполнение невыполненного оператора в обработчике исключений.

Таблица Def:

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
...