2010-01-27 5 views
3

Я ошибки, в результате объемной операции вставки, как это:Oracle DML ошибки, не имеющие деталей

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)

ответ

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 

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

Таблица 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 
+0

@Daniel ОМГЭ: Ммм да это имеет смысл. Стреляйте! Я полагаю, что% BULK_EXCEPTIONS не хранит детали конкретной ошибки, поэтому то, что я пытаюсь сделать, вероятно, невозможно. – FrustratedWithFormsDesigner

+1

Я думал об обходном пути. Вы можете повторно выполнить оператор в обработчике исключений для каждой неудавшейся строки. Затем вы можете поймать это исключение, которое будет иметь имя ограничения. –

+0

Эй, это очень умно! Благодаря! :) – FrustratedWithFormsDesigner