2016-04-19 44 views
0

因此,我必須創建一個觸發器,將一個名爲'passengerlist1'的表所做的更改記錄到名爲'logs'的額外表中。ORA-04091:表xx_xx正在變異,觸發器/函數可能看不到它

日誌表:

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。這是從哪裏我需要選擇一個人的給定名稱和家族姓名的表格,並將其存儲到「日誌」表格中,以便對'passengerlist1'表格進行更改。從'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表,是我定義這觸發爲AFTER觸發器,我期待更改先生效,然後觸發器將插入到'日誌'表中。而是我得到這個錯誤:

ORA-04091:表xx_passengerlist1都在變異,觸發/功能可能無法看到它

我到底做錯了什麼?先謝謝你。

回答

1

您無法查詢觸發器中的變異表。
看到這個: https://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm

Trigger Restrictions on Mutating Tables

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.

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

+1的鏈接和解決方案!非常感謝!我終於明白爲什麼會出現這個錯誤,以及如何避免它在未來。 @kordirko –

相關問題