сохранение исключений не захватывает полное описание ошибки для ORA-01438 - PullRequest
0 голосов
/ 06 августа 2020

Исключения сохранения не захватывают полное описание ошибки для ORA-01438: значение больше, чем указанная точность, разрешенная для этого столбца , это вызывает только общую ошибку c, без имени столбца и размер захвачен. С этим кодом можно интегрировать любое обходное решение для получения полного описания столбца, связанного с ошибкой?

   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

1 Ответ

1 голос
/ 07 августа 2020

Как Oracle указывает

Добавьте предложение SAVE EXCEPTIONS в ваш оператор FORALL, если вы хотите, чтобы механизм выполнения PL / SQL выполнял все операторы DML, сгенерированные FORALL, даже если один или более чем выйти из строя с ошибкой. Если вы используете ИНДЕКСЫ OF, вам нужно будет немного позаботиться о том, чтобы вернуться к ошибочному утверждению.

Итак, СОХРАНИТЬ ИСКЛЮЧЕНИЯ делает то, что должно делать, поэтому весь FORALL, не поднимая до конца никаких вопросов. Ваша проблема здесь ORA-01438: value larger than specified precision allowed for this column. Это исключение никогда не проинформирует затронутый столбец. Чтобы зафиксировать проблемный столбец c, у вас есть несколько вариантов.

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 ERROR ЖУРНАЛ

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

В вашем коде c вы должны:

1. Создайте ТАБЛИЦУ ОШИБОК для своей таблицы exception_test с помощью DBMS_ERRLOG.

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

2. Измените ЗАЯВЛЕНИЕ INSERT, чтобы добавить предложение 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;

UPDATE

Вариант для вашего кода

EXE C 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;
   / 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...