当我更新表中的数据时,我收到'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;
答案 0 :(得分: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;
答案 1 :(得分:0)
当触发器引用拥有触发器的表时,会发生Oracle变异触发器错误,从而导致" ORA-04091:表名发生变异,触发器/函数可能看不到它。"消息。
不要使用触发器 - 避免变异表错误的最佳方法是不使用触发器。虽然面向对象的Oracle提供了"方法"与表相关联的,除非绝对必要,否则大多数精明的PL / SQL开发人员都会避免使用触发器。
使用""或"而不是"触发器 - 如果必须使用触发器,最好通过使用""来避免变异表错误。触发,以避免与变异表相关的货币问题。例如,使用触发器":在xxx"上更新后,原始更新已完成,表格不会发生变异。
重新设计触发器语法 - 避免使用行级和语句级触发器的组合来改变表。
使用自治事务 - 您可以通过将触发器标记为自治事务来避免变异表错误,使其独立于调用该过程的表。