【问题标题】:How do I fix ORA-04091: table is mutating, trigger/function may not see it?如何修复 ORA-04091:表正在变异,触发器/函数可能看不到它?
【发布时间】: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;

我能做些什么来解决它?

【问题讨论】:

    标签: oracle plsql triggers


    【解决方案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)。可以像普通表一样查询

    【讨论】:

    • 是的,这是更好的选择,只要触发器不仅仅是允许稍后更改的初始值。
    猜你喜欢
    • 2015-06-28
    • 2010-09-27
    • 2013-11-24
    • 2016-08-11
    • 1970-01-01
    • 2022-10-20
    • 2016-04-29
    • 2019-03-12
    相关资源
    最近更新 更多