oracle變異表觸發器中ORA-04091錯誤原因及解決方案
阿新 • • 發佈:2019-02-08
變異表是指激發觸發器的DML語句所操作的表
當對一個表建立行級觸發器時,有下列兩條限制:
1.不能讀取或修改任何觸發語句的變異表; 2.不能讀取或修改觸發表的一個約束表的PRIMARYKEY,UNIQUE 或FOREIGN KEY關鍵字的列, 但
可以修改其他列
例如:有這樣一個需求:在更新員工所在部門或向部門插入新員工時,部門中員工人數不超過7人
如果按照下面的觸發器寫就會使UPDATE操作時報錯
CREATE OR REPLACE TRIGGER updatetrigger BEFORE UPDATE ON EMP FOR EACH ROW DECLARE v_num NUMBER; BEGIN SELECT count(*) INTO v_num FROM emp WHERE deptno = :new.deptno; IF (v_num > 7) THEN RAISE_APPLICATION_ERROR(-20001, '員工數多於'||v_num); END IF; END updatetrigger;
ORA-04091: 表 SCOTT.EMP 發生了變化, 觸發器/函式不能讀它
ORA-06512: 在 "SCOTT.UPDATETRIGGER", line 4
ORA-04088: 觸發器 'SCOTT.UPDATETRIGGER' 執行過程中出錯
如果既想更新變異表,同時又需要查詢變異表,那麼如何處理呢?
將行級觸發器與語句級觸發器結合起來,在行級觸發器中獲取要修改的記錄的資訊,存放到一個軟體包的全域性變數中,然後在語句級後觸發器中利用軟體包中全域性變數資訊對變異表的查詢,並根據查詢的結果進行業務處理
例如:
為了實現在更新員工所在部門或向部門插入新員工時,部門中員工人數不超過7人,可以在emp表上建立兩個觸發器,同時建立一個共享資訊的包
CREATE OR REPLACE PACKAGE mutate_pkg AS v_deptno NUMBER(2); END; CREATE OR REPLACE TRIGGER rmutate_trigger BEFORE INSERT OR UPDATE OF deptno ON EMP FOR EACH ROW BEGIN mutate_pkg.v_deptno:=:new.deptno; END; CREATE OR REPLACE TRIGGER smutate_trigger AFTER INSERT OR UPDATE OF deptno ON EMP DECLARE v_num number(3); BEGIN SELECT count(*) INTO v_num FROM emp WHERE deptno = mutate_pkg.v_deptno; IF v_num>7 THEN RAISE_APPLICATION_ERROR(-20003,'這部門的員工太多了 '|| mutate_pkg.v_deptno); END IF; END;
這樣操作,就不會報ORA-04091: 表SCOTT.EMP 發生了變化,觸發器/函式不能讀它錯誤了