Почему триггер AFTER UPDATE (FOR EACH ROW) срабатывает до (НЕ ОТЛОЖЕННОЙ) проверки ограничения целостности? - PullRequest
0 голосов
/ 05 августа 2020

Я изучаю триггеры, используя Oracle 12 c HR образец схемы и Oracle Develop PL/SQL Program Units руководство для студентов. Oracle говорит, что модель выполнения триггера:

  1. Выполнить все триггеры BEFORE STATEMENT.
  2. L oop для каждой строки, затронутой оператором SQL:
  3. Выполнить все триггеры BEFORE ROW для этой строки.
  4. Выполнить оператор DML И ВЫПОЛНИТЬ ПРОВЕРКУ ОГРАНИЧЕНИЙ ЦЕЛОСТНОСТИ ДЛЯ ЭТОЙ СТРОКИ .
  5. Выполнить все триггеры AFTER ROW для этой строки row.
  6. Выполнить все триггеры AFTER STATEMENT.

В примере схемы HR есть таблица EMPLOYEES с DEPARTMENT_ID FK, возвращающая DEPARTMENT_ID PK в DEPARTMENTS таблица.

Правильно, если я попытаюсь вставить запись в EMPLOYEES, имеющую значение FK, которого нет среди PK в DEPARTMENTS, я получу ошибку ORA-02291: integrity constraint (HR.EMP_DEPT_FK) violated - parent key not found.

В качестве доказательства концепции я создаю следующий триггер BEFORE UPDATE, чтобы вставить отсутствующую запись в DEPARTMENTS и избежать нарушения ограничения целостности:

CREATE OR REPLACE TRIGGER employee_dept_fk_trg
  BEFORE UPDATE OF department_id ON employees 
  FOR EACH ROW
BEGIN
  INSERT INTO departments (department_id, department_name) VALUES(:new.department_id,'Dept '||:new.department_id);
EXCEPTION
  WHEN DUP_VAL_ON_INDEX THEN
    NULL; -- mask exception if department already exists
END;

Работает нормально ( Я могу вставить несуществующий FK, так как соответствующий PK будет создан f irst).

В учебном материале сказано, что мы могли бы сделать HR.EMP_DEPT_FK ограничение DEFERRABLE INITIALLY DEFERRED, чтобы отложить проверку целостности на момент финальной COMMIT, а не в конце каждого INSERT (см. Пункт 4 в списке), и поэтому создайте триггер AFTER UPDATE, а не BEFORE UPDATE, как в предыдущем.

Есть ли какие-либо преимущества в этом по сравнению с использованием BEFORE UPDATE trigger?

Перед изменением ограничения HR.EMP_DEPT_FK, устанавливающего его DEFERRABLE INITIALLY DEFERRED, я хотел проверить утверждение в пункте 4, поэтому я создал идентичный AFTER UPDATE триггер и попытался вставить несуществующий FK в таблице сотрудников: Я ПОЛУЧИЛ NO ORA-02291 ERROR, и новая запись PK в таблице DEPARTMENTS создана! Кажется, что триггер AFTER UPDATE срабатывает до проверки ограничений целостности, хотя это должно произойти после! (см. пункт 5)

Не могли бы вы мне помочь с этим топи c, пожалуйста?

Всем спасибо, Пино

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