ORA-04091:表xx_xx正在变异,触发器/功能可能看不到它 [英] ORA-04091: table xx_xx is mutating, trigger/function may not see it

查看:83
本文介绍了ORA-04091:表xx_xx正在变异,触发器/功能可能看不到它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我必须创建一个触发器,该触发器将对名为"passengerlist1"的表所做的更改记录到名为"logs"的附加表中.

So i have to create a trigger which will log changes made to a table called 'passengerlist1' into an extra table called 'logs'.

日志表:

create table logs (
  p_name varchar(255),
  p_surname varchar(255),
  f_id number,
  time_stamp timestamp
);

Passengerlist1表具有以下属性: FLIGHTID,PERSONID,SEATNUMBER.

Passengerlist1 table has the following attributes: FLIGHTID, PERSONID, SEATNUMBER.

还有另一个名为PERSON1的表,具有以下属性: PERSONID,GIVENNAME,FAMILYNAME,DATEOFBIRTH.这是我需要从中选择一个人的给定名称和姓氏并将其存储到该表中的表.如果对"passengerlist1"表进行了更改,则使用"logs"表.从"passengerlist1"表中,我只需要选择FLIGHTID并将其存储到"logs"表中.

There is another table involed called PERSON1 with attributes: PERSONID, GIVENNAME, FAMILYNAME, DATEOFBIRTH. This is the table from where i need to select the givenname and familyname of a person and store it into the 'logs' table in case changes are made to 'passengerlist1' table. From 'passengerlist1' table i only need to select the FLIGHTID and store it into the 'logs' table.

因此,这就是我的触发器:

So with this out of the way here is my trigger:

CREATE OR REPLACE TRIGGER log_changes 
  AFTER INSERT OR UPDATE OR DELETE
  ON passengerlist1
  FOR EACH ROW

DECLARE
 t_name varchar2(255);
 t_surname varchar2(255);
BEGIN
  BEGIN

   IF DELETING THEN
    SELECT PERSON1.GIVENNAME INTO T_NAME FROM 
      PERSON1 JOIN PASSENGERLIST1 
      ON PERSON1.PERSONID = PASSENGERLIST1.PERSONID
      WHERE PASSENGERLIST1.FLIGHTID = :OLD.FLIGHTID;

    SELECT PERSON1.FAMILYNAME INTO T_SURNAME FROM 
      PERSON1 JOIN PASSENGERLIST1 
      ON PERSON1.PERSONID = PASSENGERLIST1.PERSONID
      WHERE PASSENGERLIST1.FLIGHTID = :OLD.FLIGHTID;

    INSERT INTO LOGS VALUES (T_NAME, T_SURNAME, :OLD.FLIGHTID, SYSDATE);
   END IF;

   IF UPDATING THEN

    SELECT PERSON1.GIVENNAME INTO T_NAME FROM 
      PERSON1 JOIN PASSENGERLIST1 
      ON PERSON1.PERSONID = PASSENGERLIST1.PERSONID
      WHERE PASSENGERLIST1.FLIGHTID = :NEW.FLIGHTID;

     SELECT PERSON1.FAMILYNAME INTO T_SURNAME FROM 
      PERSON1 JOIN PASSENGERLIST1 
      ON PERSON1.PERSONID = PASSENGERLIST1.PERSONID
      WHERE PASSENGERLIST1.FLIGHTID = :NEW.FLIGHTID;

    INSERT INTO LOGS VALUES (T_NAME, T_SURNAME, :NEW.FLIGHTID, SYSDATE);
   END IF;

   IF INSERTING THEN
      SELECT PERSON1.GIVENNAME INTO T_NAME FROM 
      PERSON1 JOIN PASSENGERLIST1 
      ON PERSON1.PERSONID = PASSENGERLIST1.PERSONID
      WHERE PASSENGERLIST1.FLIGHTID = :NEW.FLIGHTID;

     SELECT PERSON1.FAMILYNAME INTO T_SURNAME FROM 
      PERSON1 JOIN PASSENGERLIST1 
      ON PERSON1.PERSONID = PASSENGERLIST1.PERSONID
      WHERE PASSENGERLIST1.FLIGHTID = :NEW.FLIGHTID;

      INSERT INTO LOGS VALUES (T_NAME, T_SURNAME, :NEW.FLIGHTID, SYSDATE);
   END IF;
END;
END;
/

现在使用以下匿名块:

begin
 delete from passengerlist1 where flightid = 1;
end;
/

要对passengerlist1表进行一些更改,因为我将该触发器定义为 AFTER 触发器,我希望更改首先生效,然后该触发器将触发插入到日志"中桌子.但是相反,我得到了这个错误:

to make some changes to passengerlist1 table, being that i defined this trigger as an AFTER trigger, i was expecting the changes to take effect first, then the trigger would fire insert into the 'logs' table. But instead i get this error:

ORA-04091:表xx_passengerlist1正在突变,触发器/函数可能看不到

我在做什么错?预先谢谢你.

What am i doing wrong? Thank you in advance.

推荐答案

您无法在触发器中查询变异表.
看到这个: https://docs.oracle.com/cd/B19306_01/appdev .102/b14251/adfns_triggers.htm

You can't query a mutating table in the trigger.
See this: https://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm

突变表的触发限制

变异表是由UPDATE修改的表, DELETE或INSERT语句,或者可能由表更新的表 DELETE CASCADE约束的效果.

A mutating table is a table that is being modified by an UPDATE, DELETE, or INSERT statement, or a table that might be updated by the effects of a DELETE CASCADE constraint.

发出触发语句的会话无法查询或 修改变异表.此限制可防止触发 看到一组不一致的数据.

The session that issued the triggering statement cannot query or modify a mutating table. This restriction prevents a trigger from seeing an inconsistent set of data.

此限制适用于所有使用FOR EACH ROW的触发器 条款.不考虑在INSTEAD OF触发器中修改的视图 变异.

This restriction applies to all triggers that use the FOR EACH ROW clause. Views being modified in INSTEAD OF triggers are not considered mutating.

当触发器遇到变异表时,会发生运行时错误, 触发主体和触发语句的效果会发生变化 返回,并将控制权返回给用户或应用程序.

When a trigger encounters a mutating table, a runtime error occurs, the effects of the trigger body and triggering statement are rolled back, and control is returned to the user or application.

请尝试以下代码:

create or replace 
TRIGGER log_changes 
  AFTER INSERT OR UPDATE OR DELETE
  ON passengerlist1
  FOR EACH ROW

DECLARE
 t_name varchar2(255);
 t_surname varchar2(255);
BEGIN
   IF DELETING THEN
    SELECT PERSON1.GIVENNAME, PERSON1.FAMILYNAME INTO T_NAME,  T_SURNAME
    FROM PERSON1
    WHERE PERSON1.PERSONID = :OLD.PERSONID;

    INSERT INTO LOGS VALUES (T_NAME, T_SURNAME, :OLD.FLIGHTID, SYSDATE);
   END IF;

   IF UPDATING OR INSERTING THEN

     SELECT PERSON1.GIVENNAME,  PERSON1.FAMILYNAME  INTO T_NAME, T_SURNAME 
     FROM PERSON1 
     WHERE PERSON1.PERSONID = :NEW.PERSONID;

     INSERT INTO LOGS VALUES (T_NAME, T_SURNAME, :NEW.FLIGHTID, SYSDATE);
   END IF;
END;
/

这篇关于ORA-04091:表xx_xx正在变异,触发器/功能可能看不到它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆