错误触发器:表正在变异,触发器/函数可能看不到它

Posted

技术标签:

【中文标题】错误触发器:表正在变异,触发器/函数可能看不到它【英文标题】:Error Trigger : Table is mutating, trigger/function may not see it 【发布时间】:2016-10-29 14:17:59 【问题描述】:

我写了这个触发器

CREATE OR REPLACE TRIGGER update_expirationDate
AFTER INSERT ON DIFFUSION FOR EACH ROW
DECLARE
    lastdiffusion DATE;
BEGIN
    SELECT MAX(diffusionDate) INTO lastdiffusion FROM DIFFUSION WHERE idEpisode = :NEW.idEpisode;
    UPDATE EPISODE SET expirationDate = lastdiffusion + 14 WHERE idEpisode = :NEW.idEpisode;
END;
/

编译没问题,但是当我在 DIFFUSION 中插入一些值时,出现以下错误:

ORA-04091: table DIFFUSION is mutating, trigger/function may not see it

我不明白是什么问题..

有人可以帮助我并告诉我我做错了什么吗?谢谢。

【问题讨论】:

几天前我回答了一个类似的question。 【参考方案1】:

问题在于您正在引用触发器本身中正在更新的表。甲骨文感到困惑。而且,如果你足够认真地考虑这一点,你可能也会感到困惑。

幸运的是,在这种情况下,我认为您不需要引用该表。相反,只需在update 上使用逻辑:

CREATE OR REPLACE TRIGGER update_expirationDate
AFTER INSERT ON DIFFUSION FOR EACH ROW
BEGIN
    UPDATE EPISODE
        SET expirationDate = :NEW.diffusionDate + 14
        WHERE idEpisode = :NEW.idEpisode AND
              expirationDate < :NEW.diffusionDate + 14;
END;

也就是说,仅在值将要更改时更新expirationDate。如果您对每个插入都这样做,那么它将始终是最大值。

【讨论】:

谢谢!这正是我想做的事情【参考方案2】:

只是不要在另一个查询中使用触发器的同一个表,这会导致冗余。

【讨论】:

【参考方案3】:

使用复合触发器,它解决了你的问题。

This article 包含更多信息。

【讨论】:

您能否将链接中的知识应用于您的答案中的问题?否则,这应该是对问题的评论而不是答案。

以上是关于错误触发器:表正在变异,触发器/函数可能看不到它的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 ORA-04091:表正在变异,触发器/函数可能看不到它?

ORA-04091: 表 [blah] 正在变异,触发器/函数可能看不到它

表正在变异,触发器/函数可能看不到它;需要后/行级查询

表正在变异,触发器/函数可能看不到它/ORA-04088: 执行触发器时出错

表正在变异,触发器可能看不到它

ORA-04091: 表 JOSEP.EMP 正在变异,触发器/函数可能看不到它