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

Oracle ORA-04091:表xx_xx正在变异,触发器/函数可能看不到它,oracle,plsql,triggers,Oracle,Plsql,Triggers,因此,我必须创建一个触发器,它将对名为“passengerlist1”的表所做的更改记录到名为“logs”的额外表中 日志表: create table logs ( p_name varchar(255), p_surname varchar(255), f_id number, time_stamp timestamp ); Passengerlist1表具有以下属性:FLIGHTID、PERSONID、SEATNUMBER。 还有另一个名为PERSON1的表,其属性为:P

因此,我必须创建一个触发器,它将对名为“passengerlist1”的表所做的更改记录到名为“logs”的额外表中

日志表:

create table logs (
  p_name varchar(255),
  p_surname varchar(255),
  f_id number,
  time_stamp timestamp
);
Passengerlist1表具有以下属性:FLIGHTID、PERSONID、SEATNUMBER。

还有另一个名为PERSON1的表,其属性为:PERSONID、GIVENNAME、FAMILYNAME、DATEOFBIRTH。这是一个表,我需要从中选择一个人的GIVENNAME和FAMILYNAME,并将其存储到“logs”表中,以防对“PassengerList 1”表进行更改。从“passengerlist1”表中,我只需要选择FLIGHTID并将其存储到“logs”表中

这是我的扳机:

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表进行一些更改,因为我将此触发器定义为触发器之后的,我希望这些更改首先生效,然后触发器将触发insert到“logs”表中。但是我得到了这个错误:

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


我做错了什么?提前谢谢。

您不能在触发器中查询突变表。
见此:

对变异表的触发限制

变异表是一个正在被更新修改的表, DELETE、INSERT语句或可能由 删除级联约束的效果

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

此限制适用于对每行使用 条款不考虑在而不是触发器中修改的视图 变异

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

请尝试以下代码:

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;
/