SQL 错误:ORA-04091:表正在更改,触发器/函数可能看不到它



当我更新表中的数据时,我收到"SQL错误:ORA-04091:表正在更改,触发器/函数可能看不到它"。

DDL:

CREATE TABLE STUDENT_DIM (STUD_ID NUMBER,CURR_STUD_NAME VARCHAR2(30),PREV_STUD_NAME VARCHAR2(30), CURR_DOJ DATE, PREV_DOJ DATE, CURRR_DEPT_NAME VARCHAR2(30),PREV_DEPT_NAME VARCHAR2(30));
INSERT INTO STUDENT_DIM(STUD_ID,CURR_STUD_NAME,CURR_DOJ,CURRR_DEPT_NAME) VALUES(1,'VINOTH','01-AUG-2017','CSE');
INSERT INTO STUDENT_DIM(STUD_ID,CURR_STUD_NAME,CURR_DOJ,CURRR_DEPT_NAME) VALUES(2,'SURESH','11-SEP-2017','ECE');
INSERT INTO STUDENT_DIM(STUD_ID,CURR_STUD_NAME,CURR_DOJ,CURRR_DEPT_NAME) VALUES(3,'RAM','01-MAY-2018','IT');

触发:

CREATE OR REPLACE TRIGGER STUDENT_DIM_HIST BEFORE UPDATE ON STUDENT_DIM FOR EACH ROW
BEGIN
CASE WHEN UPDATING('CURR_STUD_NAME') THEN UPDATE STUDENT_DIM SET PREV_STUD_NAME = :OLD.CURR_STUD_NAME WHERE STUD_ID = :OLD.STUD_ID;
WHEN UPDATING('CURR_DOJ')       THEN UPDATE STUDENT_DIM SET PREV_DOJ = :OLD.CURR_DOJ WHERE STUD_ID = :OLD.STUD_ID;
WHEN UPDATING('CURRR_DEPT_NAME') THEN UPDATE STUDENT_DIM SET PREV_DEPT_NAME = :OLD.CURRR_DEPT_NAME WHERE STUD_ID = :OLD.STUD_ID;
END CASE;
END;

更新:

UPDATE STUDENT_DIM SET CURR_STUD_NAME = 'RAM KUMAR' WHERE STUD_ID = 3;

当触发器引用拥有该触发器的表时,会发生 Oracle 突变触发器错误,从而导致"ORA-04091:表名正在变异,触发器/函数可能看不到它"消息。

  1. 不要使用触发器 - 避免更改表错误的最佳方法是不使用触发器。 虽然面向对象的Oracle提供了与表相关的"方法",但大多数精明的PL/SQL开发人员都避免触发器,除非绝对必要。

  2. 使用"之后"或"代替"触发器 - 如果必须使用触发器,最好使用"之后"触发器来避免更改表错误,以避免与更改表关联的货币问题。 例如,使用触发器":after update on xxx",原始更新已完成,表不会发生变化。

  3. 重新设计触发器语法 - 避免使用行级和语句级触发器的组合来改变表。

  4. 使用自主事务 - 通过将触发器标记为自治事务,使其独立于调用过程的表,可以避免变异表错误。

在操作(更新)同一表期间,触发器尝试引用拥有触发器的,因此问题引发。

请改用一些赋值,如下所示:

CREATE OR REPLACE TRIGGER STUDENT_DIM_HIST BEFORE UPDATE ON STUDENT_DIM FOR EACH ROW
BEGIN
CASE WHEN UPDATING('CURR_STUD_NAME')  THEN :NEW.PREV_STUD_NAME := :OLD.CURR_STUD_NAME;
WHEN UPDATING('CURR_DOJ')        THEN :NEW.PREV_DOJ       := :OLD.CURR_DOJ;
WHEN UPDATING('CURRR_DEPT_NAME') THEN :NEW.PREV_DEPT_NAME := :OLD.CURRR_DEPT_NAME;
END CASE;
END;

相关内容

最新更新