Я хочу, чтобы этот триггер вставлял данные в таблицу аудита, а также выдавал ошибку. Но это только вызывает ошибку, но данные не вставляются - PullRequest
0 голосов
/ 16 ноября 2018

Это триггер, чтобы проверить, больше ли фактическая зарплата, чем максимальная зарплата. Но это только вызвало ошибку и не записало данные в таблицу аудита. Я хочу, чтобы этот триггер вставлял данные, а также вызывал ошибку.

     Create or replace trigger trg_audit
     BEFORE UPDATE ON lds_placement
     for each row
    BEGIN  
    if :NEW.actual_salary>:new.max_salary then

    insert into pradip_audit_table(audit_date, table_name, operation_type, 
    primary_key_column, primary_key_value,
   column_affected, max_salary, actual_salary, host, ip_adddress, terminal ) 
   values (sysdate, 
    'lds_placement',
    'update', 
    'plt_id', 
     :OLD.placement_id,
     'actual_salary', 
    :new.max_salary, 
    :NEW.actual_salary,
    sys_context('USERENV', 'HOST'),
    sys_context('USERENV', 'IP_ADDRESS', 15),
    sys_context('USERENV', 'TERMINAL'));

   raise_application_error(-20111, 'Salary cannot be more than maximum 
    salary');

end if;
  end;

Ответы [ 3 ]

0 голосов
/ 16 ноября 2018

С Документация :

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

Oracle создает неявную точку сохранения перед вашим оператором update, и если обновление или триггер вызывают исключение, транзакция откатывается до этой точки сохранения. Решение состоит в том, чтобы создать отдельную процедуру для вставки, отметить ее как pragma AUTONOMOUS_TRANSACTION и выполнить фиксацию в этой процедуре; тогда вставленные вами данные не будут откатываться при сбое триггера.

0 голосов
/ 16 ноября 2018

Все, что вы делаете в триггере, будет следовать судьбе всей транзакции. Если вы вставите данные, а затем создадите исключение, вся операция будет отменена.

Вам необходимо выполнить вставку в ДРУГОЙ СДЕЛКЕ. oracle позволяет определять функции и процедуры, которые выполняются в отдельной транзакции от транзакции вызывающей программы. Вы даже можете определить эти процедуры как локальные процедуры.

Это то, что вам нужно:

 Create or replace trigger trg_audit  
 AFTER UPDATE ON lds_placement
 for each row
 declare 

     procedure WriteAuditLog is
     pragma autonomous_transaction;
     begin
          insert into pradip_audit_table(
              audit_date, table_name, operation_type,  primary_key_column, primary_key_value,
             column_affected, max_salary, actual_salary, host, ip_adddress, terminal 
          ) 
         values 
         (
            sysdate, 
            'lds_placement',
            'update', 
            'plt_id', 
            :OLD.placement_id,
            'actual_salary', 
            :new.max_salary, 
            :NEW.actual_salary,
            sys_context('USERENV', 'HOST'),
            sys_context('USERENV', 'IP_ADDRESS', 15),
            sys_context('USERENV', 'TERMINAL')
         );
         -- you can't leave a autonomous_transaction function without committing or rolling back:
         --    if you leave the transaction open you get an error!
         commit;                                                  
     exception when others then
        rollback;
        raise;
     end WriteAuditLog;

 BEGIN  
     if :NEW.actual_salary>:new.max_salary then
        WriteAuditLog;
        raise_application_error(-20111, 'Salary cannot be more than maximum  salary');
     end if;
 end;

Обратите внимание, что я изменил триггер для запуска ПОСЛЕ оператора, а не ДО.

  1. Перед триггерами на вашем столе может быть НЕСКОЛЬКО
  2. Каждый ПЕРЕД триггером имеет возможность изменять фактические данные, которые будут записаны
  3. У вас нет гарантии, что ваш триггер будет последним из выполненных.

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

Еще одна вещь, которая может произойти, это то, что другой триггер запускается после того, как данные «до» прошли вашу проверку, и этот второй триггер может изменить данные, например, удвоив зарплату и записав данные, которые нарушают вашу проверку, независимо от того, о том, что должен делать ваш триггер.

Триггеры ПОСЛЕ не могут изменить данные, поскольку они уже записаны, поэтому правильное место для такого рода проверок и регистрации - триггер ПОСЛЕ.

Обратите внимание, что при возникновении исключения команда обновления будет отменена, даже если вы находитесь в триггере AFTER: не позволяйте слову "AFTER" вводить вас в заблуждение.

0 голосов
/ 16 ноября 2018

Советую использовать автономную транзакцию в отдельной процедуре для вставки в таблицу аудита для этого случая.Есть документация https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/autonotransaction_pragma.htm

Проблема в том, что вы не делаете коммит после вставки.И вы не можете сделать это в триггере.Я бы предпочел сделать лог в автономной транзакции, и это должно помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...