【问题标题】:ORA-04091: table name is mutating, trigger/function may not see itORA-04091: 表名发生变化,触发器/函数可能看不到它
【发布时间】:2016-08-02 01:47:36
【问题描述】:

我有这样的触发器:

CREATE OR REPLACE TRIGGER orders_after_insert
AFTER INSERT
   ON orders
   FOR EACH ROW

DECLARE
   v_type number;

BEGIN
   SELECT type
   INTO v_type
   FROM orders
   WHERE id = :new.parent_id;

   -- do sth with v_type
END;

我收到如下错误消息:

ORA-04091: 表名发生变化,触发器/函数可能看不到它

我没有更新 orders 表中的任何行,那么有什么解决方法吗? 我只需要选择代表新记录父级的行类型,并在更新另一个表时使用此值。

【问题讨论】:

  • 为什么要在触发器中这样做;插入不能自己提供正确的类型,如果需要,查询表本身吗?
  • 这是预期的行为。请阅读其他discussion 以了解如何避免错误。

标签: sql oracle plsql


【解决方案1】:

您应该使用 PRAGMA_AUTONOMOUS_TRANSACTION 在另一个会话中检索类型列并且不会收到错误 ora-04091:

创建一个这样的函数:

CREATE OR REPLACE FUNCTION SF_GETTYPE (pParent_id NUMBER) RETURN NUMBER
IS
    pragma autonomous_transaction;
    v_type number;          
BEGIN
    SELECT type
    INTO v_type
    FROM orders
    WHERE id = pParent_id;

    RETURN v_type;
END;

修改触发器以使用函数 SF_GETTYPE :

CREATE OR REPLACE TRIGGER orders_after_insert
AFTER INSERT
   ON orders
   FOR EACH ROW

DECLARE
   v_type number;

BEGIN
   v_type := SF_GETTYPE(:new.parent_id);
   -- do sth with v_type
END;    

问候

【讨论】:

  • 您可以补充一点,不需要从订单表中选择类型,因为它已经在 :new.type 中可用
  • 他需要另一行的列类型。 :new.type 指的是当前行。
猜你喜欢
  • 2015-06-28
  • 2010-09-27
  • 2013-11-24
  • 2016-08-11
  • 1970-01-01
  • 2022-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多