oracle變異表觸發器中ORA-04091錯誤原因及解決方案

變異表是指激發觸發器的DML語句所操作的表

當對一個表創建行級觸發器時,有下列兩條限制:

1.不能讀取或修改任何觸發語句的變異表;
2.不能讀取或修改觸發表的一個約束表的PRIMARY

  KEY,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 發生了變化,觸發器/函數不能讀它錯誤了
發佈了35 篇原創文章 · 獲贊 4 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章