【问题标题】:Table is mutating, trigger/function may not see it表正在变异,触发器/函数可能看不到它
【发布时间】:2014-06-27 02:02:38
【问题描述】:

我创建了一个触发器来检查 COUNT。

create or replace
TRIGGER TEST_TRG before INSERT OR UPDATE ON TEST
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
DECLARE 
  AVAILABLE INTEGER;
BEGIN
IF UPDATING THEN
  IF(:new.STATUS = 600 OR :new.STATUS = 700) THEN
    SELECT COUNT(1) INTO AVAILABLE FROM TEST T WHERE T.IDDISPLAY = :new.IDDISPLAY 
      AND T.STATUS NOT IN (600,700);
    IF(AVAILABLE = 0) THEN
      InsertOrUpdateAnotherTable(:new.IDDISPLAY, :new.STATUS, 0);
    ELSE
      RETURN;
    END IF;
  END IF;
END IF;

我在测试表中将状态更改为600后,出现错误。

ORA-04091: table USER.TEST is mutating, trigger/function may not see it
ORA-06512: at "USER.TEST_TRG ", line 8
ORA-04088: error during execution of trigger 'USER.TEST_TRG'

如果满足条件,我将插入或更新另一个表。

错误是因为当触发器触发同一个表时,我尝试获取当前表的 COUNT。这将导致发生变异。

我尝试了 transaction_anonymous 和 Compound Trigger,但最后仍然出现同样的错误。

任何人都可以帮助我寻求另一种解决方案,拜托。

【问题讨论】:

  • 您要解决的业务问题是什么?为什么需要查询表中的行而不是正在插入或更新的行?表中行之间的依赖关系几乎总是表明数据模型存在潜在问题。
  • 抱歉造成误会。表中可能有超过 1 个 IDDISPLAY,我需要确保 IDDISPLAY 的所有状态都是 600 或 700,只有我会插入/更新另一个表 @JustinCave

标签: oracle11g


【解决方案1】:

首先:

下面这行

IF(AVAILABLE = 0) THEN

永远不会达到,即使您可以消除变异错误。 像这样检查计数:当您确实没有要查询的记录时,COUNT(1) INTO AVAILABLE 将抛出异常“找不到数据”。

其次: 使用复合触发器和 AFTER EACH ROW 部分可以避免变异,正如 Tom 写的 http://www.dba-oracle.com/t_avoiding_mutating_table_error.htm

试试这个:

create or replace
TRIGGER TEST_TRG FOR INSERT OR UPDATE ON TEST
COMPOUND TRIGGER

AVAILABLE INTEGER;

AFTER EACH ROW IS
BEGIN
IF UPDATING THEN
 IF(:new.STATUS = 600 OR :new.STATUS = 700) THEN

  BEGIN
    SELECT COUNT(1) INTO AVAILABLE FROM TEST T WHERE T.IDDISPLAY = :new.IDDISPLAY 
    AND T.STATUS NOT IN (600,700);
  EXCEPTION 
WHEN NO_DATA_FOUND THEN
  InsertOrUpdateAnotherTable(:new.IDDISPLAY, :new.STATUS, 0);
  END;

 END IF;
END IF;
END AFTER EACH ROW;
END TEST_TRG;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 2013-11-24
    • 2021-03-31
    • 2016-08-11
    • 1970-01-01
    • 2021-12-20
    相关资源
    最近更新 更多