2010-01-27 108 views
3

甲骨文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 

一个可能的解决方法是重新执行的异常处理程序失败的声明。

表防守力:

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 Emge:嗯是的,这是有道理的。射击!我猜%BULK_EXCEPTIONS不存储具体错误的细节,所以我想要做的可能是不可能的。 – FrustratedWithFormsDesigner 2010-01-27 18:50:47

+1

我想到了一个解决方法。您可以针对失败的每一行重新执行异常处理程序中的语句。然后您可以捕获具有约束名称的异常。 – 2010-01-27 19:13:24

+0

嘿,这很聪明!谢谢! :) – FrustratedWithFormsDesigner 2010-01-27 20:46:20