表是变异的,触发器/功能可能看不到它

时间:2014-06-27 02:02:39

标签: oracle11g

我创建了一个检查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 个答案:

答案 0 :(得分:0)

首先:

以下这行

IF(AVAILABLE = 0) THEN
即使您可以消除变异错误,也永远无法达到。 像这样检查计数:COUNT(1)INTO AVAILABLE将抛出异常"没有找到数据"当你真的没有记录时,你会去查询。

其次: 使用compund触发器和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;