0

保存异常未捕获ORA-01438 的完整错误描述:值大于此列允许的指定精度,它仅抛出一般错误,未捕获列名和大小。任何解决方法都可以与此代码集成以获取与错误相关的完整列描述?

   create or replace procedure BULK_COLLECT_TEST_PROC
   as
   TYPE t_bulk_collect_test_tab IS TABLE OF bulk_collect_test%ROWTYPE;

   l_tab t_bulk_collect_test_tab;
   l_error_count  NUMBER;
   ex_dml_errors EXCEPTION;
   PRAGMA EXCEPTION_INIT(ex_dml_errors, -24381);

   CURSOR c_data IS
   SELECT *
   FROM bulk_collect_test;

   BEGIN
   OPEN c_data;
   LOOP
   FETCH c_data
   BULK COLLECT INTO l_tab LIMIT 10000;
   EXIT WHEN l_tab.count = 0;    

   -- Perform a bulk operation.
   BEGIN
   FORALL i IN l_tab.first .. l_tab.last SAVE EXCEPTIONS
   INSERT INTO exception_test
   VALUES l_tab(i);
   EXCEPTION
   WHEN ex_dml_errors THEN
   l_error_count := SQL%BULK_EXCEPTIONS.count;
   DBMS_OUTPUT.put_line('Number of failures: ' || l_error_count);
   FOR i IN 1 .. l_error_count LOOP
     DBMS_OUTPUT.put_line('Error: ' || i || 
      ' Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
      ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
   END LOOP;
   END;
   END LOOP;
   END;
   /    

   SET SERVEROUTPUT ON;
   EXEC BULK_COLLECT_TEST_PROC;

   Number of failures: 9001
   Error: 1 Array Index: 1000 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 2 Array Index: 1001 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 3 Array Index: 1002 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 4 Array Index: 1003 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 5 Array Index: 1004 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 6 Array Index: 1005 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 7 Array Index: 1006 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 8 Array Index: 1007 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 9 Array Index: 1008 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 10 Array Index: 1009 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 11 Array Index: 1010 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 12 Array Index: 1011 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 13 Array Index: 1012 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 14 Array Index: 1013 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 15 Array Index: 1014 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 16 Array Index: 1015 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 17 Array Index: 1016 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 18 Array Index: 1017 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 19 Array Index: 1018 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 20 Array Index: 1019 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 21 Array Index: 1020 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 22 Array Index: 1021 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 23 Array Index: 1022 Message: ORA-01438: value larger than specified precision allowed for 
   this column
   Error: 24 Array Index: 1023 Message: ORA-01438: value larger than specified precision allowed for 
   this column
4

1 回答 1

2

正如甲骨文所说

当您希望 PL/SQL 运行时引擎执行由 FORALL 生成的所有 DML 语句时,将 SAVE EXCEPTIONS 子句添加到您的 FORALL 语句,即使一个或多个因错误而失败。如果您使用 INDICES OF,您需要小心找到返回违规语句的方法。

所以,SAVE EXCEPTIONS 正在做它应该做的事情,所以完全运行整个 FORALL,直到最后都没有引发任何问题。您的问题是ORA-01438: value larger than specified precision allowed for this column. 该异常永远不会通知受影响的列。为了捕获有问题的列,您有一些选择。

SQL

在 SQL 中,例如使用 sqlplus,您会得到一个由星号标记的列的指示,尽管该列在异常中没有明确命名。

SQL> create table t ( c1 number(1) , c2 number(2) , c3 number(3) ) ;

Table created.

SQL> insert into t values ( 1 , 22, 3333 ) ;
insert into t values ( 1 , 22, 3333 )
                               *
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column

PL/SQL

在 PL/SQL 中,异常由 EXCEPTION 模块处理,该模块控制与错误相关的 SQLCODE 和 SQLERRM。在此错误中,没有关于该列的任何指示:

SQL> declare
  2  begin
  3  insert into t values ( 1 , 22, 3333 );
  4  commit;
  5  end;
  6  /
declare
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
ORA-06512: at line 3

在这种情况下您可能会得到帮助,但会在出现异常时显示值

SQL> declare
  2  v_1 number := 1;
  3  v_2 number := 22;
  4  v_3 number := 3333;
  5  begin
  6  insert into t values ( v_1 , v_2, v_3) ;
  7  commit;
  8  exception when others then
  9    dbms_output.put_line( v_1 || '-' || v_2 || '-' || v_3 );
 10    raise;
 11* end;
SQL> /
1-22-3333
declare
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
ORA-06512: at line 10
ORA-06512: at line 6

DML 错误记录

DML ERROR LOGGING是一个非常适合您的场景的功能。您必须LOG ERRORS INTO ERROR_TABLE在创建错误表后应用该子句。

例子

SQL> EXEC DBMS_ERRLOG.CREATE_ERROR_LOG (DML_TABLE_NAME => 'T' , err_log_table_name  => 'T_ERRORS' ) ;

PL/SQL procedure successfully completed.

 declare
   v_1 number := 1;
   v_2 number := 22;
   v_3 number := 3333;
   begin
   insert into t values ( v_1 , v_2, v_3) log errors into t_errors;
   commit;
   exception when others then
       raise;
  end;
  /

ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
ORA-06512: at line 10
ORA-06512: at line 6

SQL> col c1 for a10
SQL> col c2 for a10
SQL> col c3 for a10
SQL> select ORA_ERR_NUMBER$,ORA_ERR_MESG$,c1,c2,c3 from t_errors ;

ORA_ERR_NUMBER$
---------------
ORA_ERR_MESG$
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
C1         C2         C3
---------- ---------- ----------
           1438
ORA-01438: value larger than specified precision allowed for this column
1          22         3333

在您的特定代码中,您必须:

1. 使用 DBMS_ERRLOG 为您的 exception_test 表创建一个 ERROR TABLE。

EXEC DBMS_ERRLOG.CREATE_ERROR_LOG (DML_TABLE_NAME => 'EXCEPTION_TEST' , err_log_table_name  => 'T_ERR_EXCEPTION_TEST' );

2.更改INSERT STATEMENT以添加子句LOG ERRORS INTO YOUR_ERROR_TABLE并删除SAVE EXCEPTIONS部分。使用 DML_ERROR_LOGGING 后,所有异常都将保存在错误日志表中

FORALL i IN l_tab.first .. l_tab.last 
   INSERT INTO exception_test
   VALUES l_tab(i) log errors into T_ERR_EXCEPTION_TEST;

更新

您的代码的变体

EXEC DBMS_ERRLOG.CREATE_ERROR_LOG (DML_TABLE_NAME => 'EXCEPTION_TEST' , err_log_table_name  => 'T_ERR_EXCEPTION_TEST' );

create or replace procedure BULK_COLLECT_TEST_PROC
   as
   TYPE t_bulk_collect_test_tab IS TABLE OF bulk_collect_test%ROWTYPE;
   l_tab t_bulk_collect_test_tab;
   l_error_count  NUMBER;
   
   CURSOR c_data IS
   SELECT *
   FROM bulk_collect_test;

   BEGIN
   -- first truncate error table 
   execute immediate ' truncate table T_ERR_EXCEPTION_TEST drop storage ' ;
   -- collection and insert 
   OPEN c_data;
   LOOP
   FETCH c_data
   BULK COLLECT INTO l_tab LIMIT 10000;
   EXIT WHEN l_tab.count = 0;    

   -- Perform a bulk operation.
   BEGIN
   FORALL i IN l_tab.first .. l_tab.last 
   INSERT INTO exception_test VALUES l_tab(i) log errors into T_ERR_EXCEPTION_TEST ;
   END LOOP;
   -- count errors
   commit ;
   select count(*) into l_error_count from T_ERR_EXCEPTION_TEST;
   if l_error_count > 0 
   then 
       -- loop over the errors if you want to here by selecting the error 
       -- table
       null;
   end if;
   EXCEPTION 
   WHEN OTHERS THEN RAISE;
   END;
   END LOOP;
   END;
   / 
于 2020-08-06T22:02:32.560 回答