【问题标题】:SQL Error: ORA-04091: table is mutating, trigger/function may not see itSQL 错误: ORA-04091: table is mutating, trigger/function may not see it
【发布时间】:2018-05-05 11:04:16
【问题描述】:

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

【问题讨论】:

    标签: sql oracle plsql database-trigger


    【解决方案1】:

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

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

    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;
    

    【讨论】:

      【解决方案2】:

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

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

      2. 使用“after”或“instead of”触发器 - 如果必须使用触发器,最好使用“after”触发器来避免变异表错误,以避免与变异相关的货币问题桌子。例如,使用触发器“:after update on xxx”,原来的更新已经完成,表不会发生变异。

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

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

      【讨论】:

        猜你喜欢
        • 2015-12-19
        • 2023-01-26
        • 2011-10-18
        • 2016-03-07
        • 2012-09-11
        • 2018-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多