ORA-04091“更新后”触发器错误,如何解决?

Posted

技术标签:

【中文标题】ORA-04091“更新后”触发器错误,如何解决?【英文标题】:ORA-04091 Error on "after update" trigger, how to get around? 【发布时间】:2019-07-27 23:12:08 【问题描述】:

我有一个触发器设置为在更新特定列后触发。我想在另一列的特定值更改为另一个特定值后更新特定列的值。

我收到了错误:

ORA-04091: table tableName is mutating, trigger/function may not see it
ORA-06512: at "triggerName", line 14
ORA-04088: error during execution of trigger 'triggerName'

我已将其重写为更新前和更新后,并尝试将逻辑存储在函数中,并使用“pragma automatic_transaction”,但仍然会抛出错误。


BEFORE update of columnName1 ON tableName
FOR EACH ROW
BEGIN

    if :new.columnName1 = 3 AND :old.columnName1 = 1 then    
    update tablename
        set columnName2= MOD(sequenceName.NextVal, 5) + 1  
        where tableName.columnName2 = :old.columnName2;
    end if;
END;
/

当我不更新受触发器响应的更新影响的列时,我不明白为什么整个表都被标记为“变异”。当然,如果表中的另一个值发生变化,您应该能够更新表中列的值,还是我在这里疯了?

注意:一次只会影响一个条目。在我的应用程序逻辑中,我更新了数据库中某个人的状态。我希望数据库只对特定的状态变化做一些逻辑,并且我想避免对这里的逻辑使用 API 调用,正如你所看到的,它只是 PLSQL 中的一行逻辑。

谢谢

【问题讨论】:

ORACLE After update trigger: solving ORA-04091 mutating table error的可能重复 @OldProgrammer 你是对的,尽管这个线程有实际的代码。如果你愿意,可以标记为重复 【参考方案1】:

也许您真的不想更新表格,而只是更改正在更新的特定行中的值。

如果是这样,请避开 update 并设置值:

BEFORE update of columnName1 ON tableName
FOR EACH ROW
BEGIN

    if :new.columnName1 = 3 AND :old.columnName1 = 1 then    
       :new.columnName2 := MOD(sequenceName.NextVal, 5) + 1 ; 
    end if;
END;

【讨论】:

我猜你的意思是:new.columnName2 := MOD(...

以上是关于ORA-04091“更新后”触发器错误,如何解决?的主要内容,如果未能解决你的问题,请参考以下文章

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

oracle 触发器 ORA-04091

Oracle数据库如何解决ORA-04091触发器/函数不能读它的问题

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

更新后的突变表

ORA-04091 由于游标,表名在触发器中发生变化