#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. Каскадное удаление через триггер имеет для меня более высокое значение.