ORA-04091錯誤原因與解決方法
最近工作中寫了一觸發器報錯:ORA-04091:table XX is mutating, trigger/function may not see it。
下面通過官方文件及網友提供資料分析一下錯誤原因及解決方法:
1.檢視oracle官方文件:
原因:觸發器(或者被語句中引用的使用者自定義PL/SQL函式)檢視去查詢(或修改)一個被另一語句修改而觸發的表。
解決方法:重寫觸發器(或函式)避免讀該表。
2.根據錯誤原因我們寫如下觸發器,重現錯誤:
使用scott方案,建立一下表、觸發器:
-
SQL> createtable tr_table asselect *
- 表已建立。
- SQL> edit
- 已寫入 file afiedt.buf
- 1 createorreplacetrigger tr_test
- 2 afterupdateon emp
- 3 for each row
- 4 begin
- 5 update tr_table t set t.sal = (select sal from emp where empno=t.empno and empno=:new.empno);
- 6* end;
- SQL> /
- 觸發器已建立
-
SQL> update
- update emp set sal=3700 where empno=7788
- *
- 第 1 行出現錯誤:
- <span style="color:#ff0000;">ORA-04091: 表 SCOTT.EMP 發生了變化, 觸發器/函式不能讀它
- </span>ORA-06512: 在 "SCOTT.TR_TEST", line 2
- ORA-04088: 觸發器 'SCOTT.TR_TEST' 執行過程中出錯
3.原因分析:
在Oracle中執行DML語句的時候是需要顯示進行提交操作的。當我們進行插入的時候,會觸發觸發器執行對觸發器作用表和擴充套件表的種種操作,但是這個時候觸發器和插入語句是在同一個事務管理中的,因此在插入語句沒有被提交的情況下,我們無法對觸發器作用表進行其他額外的操作。如果執行其他額外的操作則會丟擲如上異常資訊。
4.解決方案:
1) 我們知道,出錯的原因是因為觸發器和DML語句在同一事務管理中,所以方案一便是將觸發器和DML語句分成兩個單獨的事務處理。這裡可以使用Pragma autonomous_transaction; 告訴Oracle觸發器是自定義事務處理。
SQL語句如下:
- createorreplacetrigger tr_test
- afterupdateon emp
- for each row
- declare
- pragma autonomous_transaction;
- begin
- update tr_table t set t.sal = (select sal from emp where empno=t.empno and empno=:new.empno);
- commit; --此處需要顯示提交
- end;
注:以上語句並不能實時獲得更新的值。。。原因是我們在update emp表後還沒來得及提交sal就觸發了觸發器,這個時候獲取到的只能是老的sal值。
2) 在Oracle Trigger中有:new,:old兩個特殊變數,當觸發器為行級觸發器的時候,觸發器就會提供new和old兩個儲存臨時行資料的特殊變數,我們可以從倆個特殊的變數中取出資料執行擴張表的DML操作。
SQL語句如下:
- createorreplacetrigger tr_test
- afterupdateon emp
- for each row
- begin
- update tr_table t set t.sal = :new.sal;
- end;
- /
5. 再次插入資料:
- SQL> update emp set sal=3800 where empno=7788;
- 已更新 1 行。
- SQL> commit;
- 提交完成。
- SQL> select * from tr_table;
- EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
- ---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
- 7369 SMITH CLERK 7902 17-12月-80 800 20
- 7499 ALLEN SALESMAN 7698 20-2月 -81 1800 300 30
- 7521 WARD SALESMAN 7698 22-2月 -81 1250 500 30
- 7566 JONES MANAGER 7839 02-4月 -81 2975 20
- 7654 MARTIN SALESMAN 7698 28-9月 -81 1250 1400 30
- 7698 BLAKE MANAGER 7839 01-5月 -81 2850 30
- 7782 CLARK MANAGER 7839 09-6月 -81 2450 10
- <span style="BACKGROUND-COLOR: #009900">7788 SCOTT ANALYST 7566 19-4月 -87 3800 20
- </span> 7839 KING PRESIDENT 17-11月-81 5000 10
- 7844 TURNER SALESMAN 7698 08-9月 -81 1500 0 30
- 7876 ADAMS CLERK 7788 23-5月 -87 1100 20
- EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
- ---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
- 7900 JAMES CLERK 7698 03-12月-81 950 30
- 7902 FORD ANALYST 7566 03-12月-81 3000 20
- 7934 MILLER CLERK 7782 23-1月 -82 1300 10
- 已選擇14行。