錯誤的原因
該錯誤是在編寫trigger時常遇到的問題,其根本原因是由於對本表的操作造成的。對於使用了for each row 的觸發器,做了DML操作(delete,update,insert),還沒有提交時,是不允許其他PL/SQL對本表的DML操作,以及查詢,因為此時數據不一致。
解決辦法:
1 自治事務
自治事物的概念:就是在subprogram里進行事物的提交不影響主程序的事務,同樣主程序的提交或回滾都不影響子程序的commit,即子程序的事物和主程序的事物完全獨立。
示例:
- CREATE OR REPLACE TRIGGER TR_T
- AFTER DELETE ON T
- FOR EACH ROW
- DECLARE V_COUNT NUMBER;
- PRAGMA AUTONOMOUS_TRANSACTION;
- BEGIN
- INSERT INTO T VALUES(:OLD.ID,:OLD.MC,SYSDATE);
- END TR_DEL_CABLE;
PRAGMA AUTONOMOUS_TRANSACTION:就是對自治事務的聲明
要注意的就是:自治事務必須慎用,因為一個DML可能會產生許多個獨立的事物,這很容易引發死鎖,ASKTOM上對AUTONOMOUS_TRANSACTION的看法是:唯一的用途就是作審計日志,其他一概不該使用。
2 網上還有人給出了另一種解決辦法:建臨時表
新建了與要操作的表結構完全相同的臨時表,使得在本表上的觸發器讀寫建好的臨時表,再用臨時表上的觸發器寫回本表,也倒是個辦法,但是不是最好的,過於繁瑣
3 治本之法:Oracle的絕大多數類型的trigger都不支持dml原表,最好是把此邏輯放到觸發器外面,另寫存儲過程實現原有功能