【问题标题】:What's wrong with that AFTER DELETE TRIGGER?删除触发器后有什么问题?
【发布时间】:2021-03-14 03:43:51
【问题描述】:

我正在尝试使用触发器在删除另一个(通过 SQL)时清除一些 @OneToOne 相关实体。假设我有一个Person 和一个OrgUnit 都引用了一些AddressAddress 映射到 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 将保留在数据库中。上面的 TRIGGER 就是用来处理这种情况的。

【问题讨论】:

  • 如果我的ADDRESS 将持有PERSON_ID(以另一种方式映射)我可以在该外键约束上使用ON DELETE CASCADE。但是现在映射是另一种方式。 ADDRESS 只是一个示例实体,实际上它以类似的方式从更多表中引用。我不想反转所有这些映射。
  • 我的猜测是地址表上有一个触发器正在对人员表执行某些操作。有吗?
  • 不,ADDRESS 上没有这样的触发器。
  • ...但是PERSON_F02ON DELETE SET NULL 可能是这里的问题吗?
  • 是的……是的。该死的……所以我不能两者兼得?

标签: oracle plsql triggers oracle12c


【解决方案1】:

所以在几次cmets之后就会弹出答案:

带有ON DELETE SET NULL 的 FK 约束会返回表并导致该异常。看来我不能两者兼得……

我将摆脱ON DELETE 定义并在这种情况下冒FK 约束错误的风险。通过触发器的级联删除对我来说具有更高的价值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 2018-03-21
    • 2011-09-06
    • 2013-12-06
    • 2021-11-28
    • 2022-01-21
    相关资源
    最近更新 更多