Как фиксировать ошибки внутри триггера

#oracle #exception #plsql #error-handling #triggers

Вопрос:

Я хочу создать триггер, который должен фиксировать все ошибки, что бы ни происходило внутри триггера. И он должен храниться в какой-то таблице журналов. Вот моя задача how to capture the error occur in DML statments . Эта ошибка состояний DML, зафиксированная в журнале respective table name along with column name and error message . Это также должно исключить все другие ошибки, такие как no_data_found, с точным номером строки.

Пожалуйста, посмотрите на мой код ниже. Если понадобятся какие-либо изменения, сообщите нам.

 create or replace TRIGGER user_name.sample_trg 
AFTER UPDATE ON user_name.transaction_tb
FOR EACH ROW
DECLARE
 variable_ln  number;
 l_err   varcha2(4000);
  
BEGIN
    select column_value
    into variable_ln
    from tb1
    where colum_1 = :NEW.colum_1
    

    IF UPDATING THEN

      INSERT
      INTO hisotry_tb
        (
          column1,
          column2,
          column3,
          column4,
        )
        VALUES
        (
          :NEW.column1,
          :NEW.column2,
          :NEW.column3,
          :NEW.column4,
        );
        
     END IF; 

IF INSERTING THEN

      INSERT
      INTO hisotry_tb
        (
          column5,
          column6,
          column7,
          column8,
        )
        VALUES
        (
          :NEW.column5,
          :NEW.column6,
          :NEW.column7,
          :NEW.column8,
        );
        
     END IF;     
        
EXCEPTION
  WHEN OTHERS THEN
    l_err := DBMS_UTILITY.FORMAT_ERROR_STACK || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE;
    INSERT INTO log (erro_msg, trigger_name, column_name) 
    VALUES (l_err, 'sample_trg', '?');
    
      DBMS_OUTPUT.put_line (l_err);
  
END;
 

Комментарии:

1. Вставка в таблицы ведения журнала должна выполняться в другой процедуре pragma autonomous_transaction , потому что ведение журнала ошибок не должно нарушать текущую транзакцию. С текущим кодом вы ничего не будете регистрировать в случае отката

2. Триггеры не должны иметь обработчика исключений, который не завершается в RAISE Исключение отклоняет эту строку (без вставки, без обновления), но для издателя DML это выглядит как завершенное действие. Если вызывающий абонент впоследствии commits не обработал эту конкретную строку. Предположим, транзакция была денежным переводом, и это была строка, которая добавилась на ваш счет. Теперь средства будут успешно зачислены на счет отправителя, но не добавлены на ваш счет. Попробуйте решить эту проблему. Вот почему даже история записи триггеров не должна принадлежать приложению с фактическим DML.

3. В качестве проблемы фрейма, как вы думаете, почему ошибка может быть связана с определенной таблицей и столбцом? Ошибка может заключаться в нарушении контрольного ограничения, включающего несколько столбцов. Ошибка может заключаться в том, что квота пользователя для любого табличного пространства, используемого таблицей, была превышена. Не имеет большого смысла привязывать это к таблице, хотя я думаю, что вы могли бы, но вы не можете привязать это к столбцу. Ошибка может заключаться history_tb в том, что при неудачной проверке существует триггер.

4. КСТАТИ: В настоящее время нет необходимости проверять «Если ОБНОВЛЕНИЕ» или If INSERTING . Как написано, триггер срабатывает только при вставке npdate, а не при вставке. Это то, что AFTER UPDATE уточняет.

5. Вы можете получить сообщение об ошибке. Вы можете узнать номер линии. Ошибка может быть связана или не связана с одной или несколькими таблицами. Он может быть связан или не связан с одним или несколькими столбцами в этой таблице. Если мы ограничимся только ошибками нарушения ограничений, теоретически вы можете проанализировать сообщение об ошибке в поисках имени ограничения, а затем использовать это имя ограничения, чтобы определить, какую таблицу и столбец использовать в таблице журнала. Но это, скорее всего, будет довольно хрупкий код, и он не будет обрабатывать все возможные ошибки, которые могут возникнуть.