Что не так с этим ПОСЛЕ ТРИГГЕРА УДАЛЕНИЯ?

#oracle #plsql #triggers #oracle12c

#Oracle #plsql #триггеры #oracle12c

Вопрос:

Я пытаюсь использовать триггер для очистки некоторых @OneToOne связанных объектов при удалении другого (через SQL). Предположим, у меня есть a Person и OrgUnit оба ссылаются на некоторые Address . Это Address сопоставляется с ADDRESS_ID и связанными ограничениями внешнего ключа.

Следующий триггер компилируется просто отлично:

 CREATE OR REPLACE TRIGGER ON_DELETE_PERSON
AFTER DELETE ON PERSON
FOR EACH ROW
BEGIN
  DELETE FROM ADDRESS WHERE ID = :OLD.ADDRESS_ID;
END;
/
 

Но всякий раз, когда я пытаюсь удалить, выдается Person следующая ошибка:

 DELETE FROM PERSON WHERE ID = 21179
 
 ORA-04091: table MY_SCHEMA.PERSON is mutating, trigger/function may not see it
ORA-06512: in "MY_SCHEMA.ON_DELETE_PERSON", row 2
ORA-04088: error during execution of trigger 'MY_SCHEMA.ON_DELETE_PERSON'
 

Что нужно изменить, чтобы этот триггер заработал?

В коде Java я мог бы просто справиться с этим CascadeStyle.DELETE … но я хочу передать эту ответственность базе данных, чтобы обеспечить надлежащее ON DELETE CASCADE поведение для всех данных.

 -- CASCADE DELETE on ORGUNIT deletion...
ALTER TABLE PERSON ADD CONSTRAINT PERSON_F01
FOREIGN KEY (ORGUNIT_ID) REFERENCES ORGUNIT (ID)
ON DELETE CASCADE ENABLE VALIDATE;

-- SET NULL on ADDRESS deletion...
ALTER TABLE PERSON ADD CONSTRAINT PERSON_F02
FOREIGN KEY (ADDRESS_ID) REFERENCES ADDRESS (ID)
ON DELETE SET NULL ENABLE VALIDATE;
 

Итак, удаление ORGUNIT автоматически удаляет все связанные PERSON тоже … но ADDRESS они останутся в базе данных. Приведенный выше ТРИГГЕР предназначен для обработки этого случая.

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

1. Если бы мой ADDRESS удерживал PERSON_ID (отображался другим способом) Я мог бы использовать ON DELETE CASCADE это ограничение внешнего ключа. Но сейчас сопоставление происходит по-другому. Это ADDRESS всего лишь пример объекта, на который фактически ссылаются из многих других таблиц аналогичным образом. Я не хочу отменять все эти сопоставления.

2. Я предполагаю, что в таблице адресов есть триггер, который что-то делает с таблицей person. Есть ли?

3. Нет, такого триггера ADDRESS нет.

4. … но может ли это ON DELETE SET NULL PERSON_F02 быть проблемой здесь?

5. ДА… это так. Черт… значит, у меня не может быть обоих?

Ответ №1:

Итак, после нескольких комментариев появляется ответ:

Ограничение FK с ON DELETE SET NULL возвращает к таблице и вызывает это исключение. Похоже, у меня не может быть обоих…

В этом случае я избавлюсь от ON DELETE определения и рискну получить ошибку ограничения FK. Каскадное удаление через триггер имеет для меня более высокое значение.