【问题标题】:PLSQL Trigger Error. "is mutating, trigger/function may not see it" ORA-04091 [duplicate]PLSQL 触发错误。 “正在变异,触发器/函数可能看不到它” ORA-04091 [重复]
【发布时间】:2016-04-29 08:23:51
【问题描述】:

当我在我的 Oracle 数据库项目中声明一个触发器时,我收到一个错误,它说:

ERROR at line 1:
ORA-04091: table MIHAL277.LEAGUE_GAMES is mutating, trigger/function may not
see it
ORA-06512: at "MIHAL277.DELETE_UNUSED_GAME", line 4
ORA-04088: error during execution of trigger 'MB358996.DELETE_UNUSED_GAME'

基本上,我正在创建一个管理棋盘游戏联盟的学术项目。所以有一个游戏桌和一个联赛桌。还有一个 League_Games 表,它指示联赛中是否有游戏可用(即联赛中的玩家是否玩此游戏)。联盟可以决定停止“拥有”游戏,然后将其从 League_Games 表中删除。但是当它发生时,我想运行一个触发器,它会检查是否还有一些联赛在使用该游戏,如果没有,请从游戏表中删除特定游戏的条目。'

我的触发器是这样的:

CREATE OR REPLACE TRIGGER delete_unused_game
BEFORE DELETE ON League_Games
FOR EACH ROW
DECLARE
   deleted_game_count integer;
BEGIN
    SELECT COUNT(*) 
    INTO deleted_game_count 
    FROM League_Games 
    WHERE Game_ID = :OLD.Game_ID;
    IF deleted_game_count = 0 THEN
        DELETE FROM Game
        WHERE ID = :OLD.Game_ID;
    END IF;
END;
/

因此,当我从 Leage_Games 中删除条目时,会出现错误。这个触发器有什么问题?

【问题讨论】:

  • 有两种方法可以解决这个问题 - 使用语句触发器或使用复合触发器,在这两种方法中复合触发器可能具有更好的性能。有关使用复合触发器的示例,请参阅我对 this question 的回答。祝你好运。

标签: sql oracle plsql triggers


【解决方案1】:

您正在尝试从您正在更新的同一个表中查询数据(好吧,在这种情况下删除..)。你不能那样做,因为它是“变异的”

阅读更多关于变异触发器的信息。Tom Kyte 在这里提供了一个很好的逐步说明:

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:290416059674

还有一篇关于“触发器的问题”的博客文章:

http://www.oracle.com/technetwork/testcontent/o58asktom-101055.html

基本上,您应该重新审视您的逻辑并考虑在不使用触发器的情况下这样做;)

【讨论】:

  • 谢谢。只是为了确定:即使我更改为“删除后”也是错误的?
  • 是的,一旦你在整个表上进行聚合(即 COUNT),你就会触发变异触发器......这有点像“教科书”方式来显示变异触发器;) 阅读我提供的那些链接,之后你应该会更好地理解它。
  • 我一定会的。感谢您的帮助。
  • 如果你坚持做基于触发器,为了避免这个错误你需要切换到语句级触发器。删除“for each row”标识并确认没有现在没有league_games 的游戏,然后删除它们。它的效率较低,因为每次删除一条记录时都必须检查所有游戏,但如果数据集不是很大并且表已编入索引,它仍然应该很快。
猜你喜欢
  • 2022-10-20
  • 2015-06-28
  • 2010-09-27
  • 2013-11-24
  • 2016-08-11
  • 1970-01-01
  • 2019-03-12
  • 1970-01-01
相关资源
最近更新 更多