天天看點

oracle觸發器和事物

關于觸發器較長的描述見下面這個大牛的部落格

www.cnblogs.com/huyong/archive/2011/04/27/2030466.html

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

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觸發器、系統觸發器) 的文法格式和作用有較大差別。

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

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

create table t_test(id int,tname varchar2(20));
create table t_test1(id int,tname varchar2(20));
create table t_test2(id int,tname varchar2(20));

create or replace trigger tr_t_test
 after  insert
  on t_test
  FOR EACH ROW
  DECLARE
  i int;
begin
  i :=1;
  pro_t_test1(:NEW.id,:NEW.tname);

  -- pro_t_test2(:old.id,:old.tname);
  --rollback;
end;
/

create or replace procedure pro_t_test1(vid int, vname varchar2)
is
Pragma Autonomous_transaction;
begin
  insert into t_test1 values(vid,vname);
  commit;
end;
/
create or replace procedure pro_t_test2(vid int, vname varchar2)
is
begin
   insert into t_test2 values(vid,vname);
   commit;
end;
/
           

第一步觸發器中的“

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

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

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

SQL> insert into t_test values(1,'a');
 
insert into t_test values(1,'a')
 
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "YJQF.PRO_T_TEST2", line 5
ORA-06512: at "YJQF.TR_T_TEST", line 7
ORA-04088: error during execution of trigger 'YJQF.TR_T_TEST'
 
SQL> commit;
 
Commit complete
 
SQL> select count(*) from t_test;
 
  COUNT(*)
----------
         0
 
SQL> select count(*) from t_test1;
 
  COUNT(*)
----------
         1
 
SQL> select count(*) from t_test2;
 
  COUNT(*)
----------
         0
 
SQL> 
SQL> insert into t_test values(1,'a');
 
insert into t_test values(1,'a')
 
ORA-04092: cannot ROLLBACK in a trigger
ORA-06512: at "YJQF.TR_T_TEST", line 8
ORA-04088: error during execution of trigger 'YJQF.TR_T_TEST'
 
SQL> commit;
 
Commit complete
 
SQL> select count(*) from t_test;
 
  COUNT(*)
----------
         0
 
SQL> select count(*) from t_test1;
 
  COUNT(*)
----------
         2
 
SQL> select count(*) from t_test2;
 
  COUNT(*)
----------
         0
 
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(*)

----------

SQL>