从 table 中删除时更改 table 触发错误

Mutating table trigger error upon deleting from a table

我有这些 table 定义

CREATE TABLE EMPLOYEE(
    EmployeeID NUMBER(4),
    Name VARCHAR2(20),
    Hiredate DATE NOT NULL,
    Gender VARCHAR(1),
    DateOfBirth DATE NOT NULL,
    Salary NUMBER(8,2),
    Commission NUMBER(8, 2),
    DName VARCHAR(20),
    PName VARCHAR(20),
    Phone NUMBER(8) NOT NULL,
    GLetter VARCHAR(1),
    CONSTRAINT EMPLOYEE_EMPLOYEEID_PK PRIMARY KEY(EMPLOYEEID),
    CONSTRAINT EMPLOYEE_DNAME_FK FOREIGN KEY(DName) REFERENCES DEPARTMENT(DName) ON DELETE CASCADE,
    CONSTRAINT EMPLOYEE_PNAME_FK FOREIGN KEY(PName) REFERENCES POSITION(PName) ON DELETE CASCADE,
    CONSTRAINT EMPLOYEE_GLETTER_FK FOREIGN KEY(GLetter) REFERENCES GRADE(GLetter) ON DELETE CASCADE,
    CONSTRAINT GENDER_CK CHECK (Gender='M' or Gender='F')
);

CREATE TABLE LOGIN(
    Username VARCHAR(20),
    Password VARCHAR(20),
    EmployeeID NUMBER(4),
    CONSTRAINT LOGIN_USERNAME_PK PRIMARY KEY(Username),
    CONSTRAINT LOGIN_EMPLOYEEID_FK FOREIGN KEY(EmployeeID) REFERENCES EMPLOYEE(EmployeeID) ON DELETE CASCADE
);

CREATE SEQUENCE TRANSACTION_SEQ START WITH 6;

CREATE TABLE TRANSACTION(
    TransactionID NUMBER(4) DEFAULT TRANSACTION_SEQ.NEXTVAL,
    TransactionDate DATE, 
    Username VARCHAR(20), 
    EmployeeID NUMBER(4),
    CONSTRAINT TRANSACTION_TRANSACTIONID_PK PRIMARY KEY(TransactionID),
    CONSTRAINT TRANSACTION_USERNAME_FK FOREIGN KEY(Username) REFERENCES LOGIN(Username) ON DELETE CASCADE,
    CONSTRAINT TRANSACTION_EMPLOYEEID_FK FOREIGN KEY(EmployeeID) REFERENCES EMPLOYEE(EmployeeID) ON DELETE CASCADE
);

和这个触发器

CREATE OR REPLACE TRIGGER EMPLOYEE_TRANSACTION
    BEFORE INSERT OR UPDATE OR DELETE ON EMPLOYEE
    FOR EACH ROW
DECLARE
    ID NUMBER(4);
    USR VARCHAR(20);
BEGIN
    SELECT LOWER(USER)
    INTO USR
    FROM DUAL;
    
    SELECT EMPLOYEEID
    INTO ID
    FROM LOGIN
    WHERE USERNAME = USR;
    
    INSERT INTO TRANSACTION VALUES(DEFAULT, SYSDATE, USR, ID);
END;
/

我的问题出现在尝试删除员工时。 基本上,触发器会找出进行更改的用户的 employeeid,并将其和其他值插入事务 table。我得到这个错误:

Error report -
ORA-04091: table ---.LOGIN is mutating, trigger/function may not see it
ORA-06512: at "---.EMPLOYEE_TRANSACTION", line 9
ORA-04088: error during execution of trigger '---.EMPLOYEE_TRANSACTION'

oracle 是否考虑到我要删除的员工的 ID(将从 table LOGIN 中删除)是 oracle USER 的员工的可能性?

有什么解决办法吗?非常感谢!

如果我们假设 this fiddle 是一个可重现的测试用例来演示您的问题(请注意,我必须对您的代码进行几处更改才能执行插入测试数据等操作),问题是 login table 上的外键约束被定义为执行级联删除 (on delete cascade)。这意味着当您从 employee 中删除一行时,login 将发生变化(Oracle 正在删除子行)。因此,您无法从 employee.

上的触发器中查询它

根据您希望完成的具体目标,您有几种选择

  1. 不要查询 login table 并且不要将 employeeID 存储在 transaction table 中。如果您有在 transaction table 中执行操作的用户名,您可以随时查找他们的 employeeID.
  2. 不要使用触发器来填充 transaction table。如果您有一个删除员工的存储过程,则该过程执行记录事务的工作更有意义。
  3. 不要将约束定义为 on delete cascade。不过,这意味着您需要先删除 login 行,然后再删除 employee 行。这是 an example,我们从 LOGIN_EMPLOYEEID_FK 约束中删除 on delete cascade,并添加一条语句来删除关联的 login 行。