首页 文章

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

提问于
浏览
0

当我更新表中的数据时,我收到'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;

2 回答

  • 0

    在同一个表的操作(更新)期间,您的触发器会尝试引用拥有触发器的表,并且问题会因此而引发 .

    请改用一些分配,如下所示:

    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;
    
  • 1

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

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

    • 使用“after”或“而不是”触发器 - 如果必须使用触发器,最好通过使用“after”触发器来避免变异表错误,以避免与变异表相关联的货币问题 . 例如,使用触发器“:在xxx上更新后”,原始更新已完成,表不会发生变异 .

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

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

相关问题