1. 程式人生 > >Oracle觸發器和事務

Oracle觸發器和事務

 

oracle觸發器和事務

2015年11月24日 14:16:43 it_taojingzhan 閱讀數:320

編寫觸發器時,需要注意以下幾點:

l        觸發器不接受引數。

l        一個表上最多可有12個觸發器,但同一時間、同一事件、同一型別的觸發器只能有一個。並各觸發器之間不能有矛盾。

l        在一個表上的觸發器越多,對在該表上的DML操作的效能影響就越大。

l        觸發器最大為32KB。若確實需要,可以先建立過程,然後在觸發器中用CALL語句進行呼叫。

l        在觸發器的執行部分只能用DML語句(SELECT、INSERT、UPDATE、DELETE),不能使用DDL語句(CREATE、ALTER、DROP)

l        觸發器中不能包含事務控制語句(COMMIT,ROLLBACK,SAVEPOINT)。因為觸發器是觸發語句的一部分,觸發語句被提交、回退時,觸發器也被提交、回退了。

l        在觸發器主體中呼叫的任何過程、函式,都不能使用事務控制語句。

l        在觸發器主體中不能申明任何Long和blob變數。新值new和舊值old也不能向表中的任何long和blob列。

l        不同型別的觸發器(如DML觸發器、INSTEAD OF觸發器、系統觸發器)的語法格式和作用有較大區別。

 

關於“在觸發器主體中呼叫的任何過程、函式,都不能使用事務控制語句。” 這個可以區分一下,如果呼叫的過程中宣告的是“自治事物”是可以呼叫的。

 

建立如下三張表,一個觸發器和兩個過程

[html] view plaincopy

  1. create table t_test(id int,tname varchar2(20));  
  2. create table t_test1(id int,tname varchar2(20));  
  3. create table t_test2(id int,tname varchar2(20));  
  4.   
  5. create or replace trigger tr_t_test  
  6.  after  insert  
  7.   on t_test  
  8.   FOR EACH ROW  
  9.   DECLARE  
  10.   i int;  
  11. begin  
  12.   i :=1;  
  13.   pro_t_test1(:NEW.id,:NEW.tname);  
  14.   
  15.   -- pro_t_test2(:old.id,:old.tname);  
  16.   --rollback;  
  17. end;  
  18. /  
  19.   
  20. create or replace procedure pro_t_test1(vid int, vname varchar2)  
  21. is  
  22. Pragma Autonomous_transaction;  
  23. begin  
  24.   insert into t_test1 values(vid,vname);  
  25.   commit;  
  26. end;  
  27. /  
  28. create or replace procedure pro_t_test2(vid int, vname varchar2)  
  29. is  
  30. begin  
  31.    insert into t_test2 values(vid,vname);  
  32.    commit;  
  33. end;  
  34. /  

 

第一步觸發器中的“

[html] view plaincopy

  1. -- pro_t_test2(:old.id,:old.tname);  
  2. --rollback;  

”這兩行是沒有註釋的掉。

雖然這個觸發器可以建立成功,但是在insert操作的時候會報錯ora-04092。

[html] view plaincopy

  1. SQL> insert into t_test values(1,'a');  
  2.    
  3. insert into t_test values(1,'a')  
  4.    
  5. ORA-04092: cannot COMMIT in a trigger  
  6. ORA-06512: at "YJQF.PRO_T_TEST2", line 5  
  7. ORA-06512: at "YJQF.TR_T_TEST", line 7  
  8. ORA-04088: error during execution of trigger 'YJQF.TR_T_TEST'  
  9.    
  10. SQL> commit;  
  11.    
  12. Commit complete  
  13.    
  14. SQL> select count(*) from t_test;  
  15.    
  16.   COUNT(*)  
  17. ----------  
  18.          0  
  19.    
  20. SQL> select count(*) from t_test1;  
  21.    
  22.   COUNT(*)  
  23. ----------  
  24.          1  
  25.    
  26. SQL> select count(*) from t_test2;  
  27.    
  28.   COUNT(*)  
  29. ----------  
  30.          0  
  31.    
  32. SQL>   
  33. SQL> insert into t_test values(1,'a');  
  34.    
  35. insert into t_test values(1,'a')  
  36.    
  37. ORA-04092: cannot ROLLBACK in a trigger  
  38. ORA-06512: at "YJQF.TR_T_TEST", line 8  
  39. ORA-04088: error during execution of trigger 'YJQF.TR_T_TEST'  
  40.    
  41. SQL> commit;  
  42.    
  43. Commit complete  
  44.    
  45. SQL> select count(*) from t_test;  
  46.    
  47.   COUNT(*)  
  48. ----------  
  49.          0  
  50.    
  51. SQL> select count(*) from t_test1;  
  52.    
  53.   COUNT(*)  
  54. ----------  
  55.          2  
  56.    
  57. SQL> select count(*) from t_test2;  
  58.    
  59.   COUNT(*)  
  60. ----------  
  61.          0  
  62.    
  63. SQL>   

 

這兩條insert雖然失敗了,但是還是寫到了t_test1表中了,在pro_t_test1上是有commit的,從這個可以看出“自主事物”是完全獨立的。

在你的主事務中,你可以選擇能夠從其他事務中進行呼叫的獨立事物。自治事務可以提交或回滾其修改而不影響呼叫它的主事務。

 

將這兩行後註釋掉後,插入就成功了。

 
SQL> insert into t_test values(1,'a');
 
1 row inserted
 
SQL> commit;
 
Commit complete
 
SQL> select count(*) from t_test;
 
  COUNT(*)
----------
         1
 
SQL> select count(*) from t_test1;
 
  COUNT(*)
----------
         3
 
SQL> select count(*) from t_test2;
 
  COUNT(*)
----------
         0

 

https://blog.csdn.net/it_taojingzhan/article/details/50012161