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

Posted

技术标签:

【中文标题】如何修复 ORA-04091:表正在变异,触发器/函数可能看不到它?【英文标题】:How do I fix ORA-04091: table is mutating, trigger/function may not see it? 【发布时间】:2020-08-20 15:51:27 【问题描述】:

我想创建一个触发器,使同一行上的 trgr 的值等于 seq+100 的值。这就是我所做的,但我不断收到错误“表正在变异,触发器/函数可能看不到它”。

CREATE OR REPLACE TRIGGER update_tgr
AFTER INSERT ON challenge FOR EACH ROW
BEGIN
    UPDATE challenge
        SET trgr = :NEW.seq + 100
        WHERE seq = :NEW.seq;
END;

我能做些什么来解决它?

【问题讨论】:

【参考方案1】:

同一行?很简单:

CREATE OR REPLACE TRIGGER update_tgr
BEFORE INSERT ON challenge FOR EACH ROW
BEGIN
  :NEW.trgr := :NEW.seq + 100;
END;

您知道您应该使用 BEFORE INSERT 触发器,因为这样您仍然可以操作新数据。

【讨论】:

您无法使用此触发器获得该错误。也许还有另一个触发错误的触发器? 我没有任何其他触发器 您真的删除了更新语句并用所示的简单赋值替换它吗? 是的。我试图用这个来激活它: INSERT INTO challenge VALUES ( 4, null ); seq 为 4,触发器为 null 如前所述,此触发器不会导致变异表错误。所以,正如你所说的没有其他触发器,一定是旧触发器没有被新触发器替换。【参考方案2】:

如果您的数据库版本是 11g+,我认为创建 Virtual Column 是一个更好的选择。因为不需要在磁盘上存储已经可以计算的列。与传统定义样式不同,这可以防止为列 (trgr) 插入错误值的可能性。然后,您可以重新创建表,例如

CREATE TABLE challenge (
  .....
  seq         INT,
  trgr        AS (seq + 100), -- [VIRTUAL]
  ----
);

无需担心已经根据表达式结果确定的数据类型(INT)。可以像普通表一样查询

【讨论】:

是的,这是更好的选择,只要触发器不仅仅是允许稍后更改的初始值。

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

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

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

ORA-04091 表 ODB.EMPLOYEE 正在变异,触发器/函数可能看不到它。我的触发器有问题吗?

ORA-04091:表正在变异,触发器/函数可能看不到它,ORA-06512:,ORA-06512:在“SYS.DBMS_SQL”,第 1721 行

ORA-04091: 表名正在变异

Oracle - 在没有触发器的情况下更新表时出现“表正在变异,触发器/函数可能看不到它”错误