1、異常出現(xiàn)的場景.
:在使用Hibernate做為項(xiàng)目持久層的情況下,,需要對某一張表進(jìn)行一個(gè)擴(kuò)展,擴(kuò)展操作便是在該表上創(chuàng)建一個(gè)觸發(fā)器,。將表中的數(shù)據(jù)讀入到其他表中,。
SQL語句如下:
- drop table tr_table;
-
- create table tr_table( --觸發(fā)器作用表
- tab_id number primary key,
- tab_name varchar2(30) NOT NULL
- )
-
- create table ts_table as select * from tr_table; --提供擴(kuò)展功能的表
-
- --定義的觸發(fā)器,,在tr_table表插入和更新數(shù)據(jù)之后向ts_table表插入當(dāng)前操作的信息行,。
- create trigger iu_table
- after insert or update on tr_table
- for each row
- begin
- --因?yàn)樵诖擞质褂昧瞬僮鱰r_table的語句而上面的insert or update在事務(wù)里
- insert into ts_table select * from tr_table t where t.tab_id = :new.tab_id;
- end is_table;
-
- --對tr_table執(zhí)行插入操作,,觸發(fā)ts_table插入操作
- insert into tr_table(tab_id,tab_name) values(1,'test');
-
- --彈出錯(cuò)誤信息提示
- --ORA-04091:表tr_table發(fā)生了變化 觸發(fā)器/函數(shù)不能讀它
- --ORA-06512: 在iu_table line 2
- --ORA-04088: 觸發(fā)器iu_table 執(zhí)行過程中出錯(cuò)
2,、問題分析
:在Oracle中執(zhí)行DML語句的時(shí)候是需要顯示進(jìn)行提交操作的,。當(dāng)我們進(jìn)行插入的時(shí)候,會觸發(fā)觸發(fā)器執(zhí)行對觸發(fā)器作用表和擴(kuò)展表的種種操作,但是這個(gè)時(shí)候觸發(fā)器和插入語句是在同一個(gè)事務(wù)管理中的,,因此在插入語句沒有被提交的情況下,我們無法對觸發(fā)器作用表進(jìn)行其他額外的操作,。如果執(zhí)行其他額外的操作則會拋出如上異常信息。
3,、解決方案
:1,我們知道,,出錯(cuò)的原因是因?yàn)橛|發(fā)器和DML語句在同一事務(wù)管理中,,所以方案一便是將觸發(fā)器和DML語句分成兩個(gè)單獨(dú)的事務(wù)處理。這里可以使用Pragma autonomous_transaction; 告訴Oracle觸發(fā)器是自定義事務(wù)處理,。
SQL語句如下:
- create trigger iu_table
- after insert or update on tr_table
- for each row
- declare --這里是關(guān)鍵的地方,在變量申明的地方,,指定自定義事務(wù)處理,。
- pragma autonomous_transaction;
- begin
- insert into ts_table select * from tr_table t where t.tab_id = :new.tab_id;
- --這里需要顯示提交事務(wù)
- commit;
- end iu_table;
:2,在Oracle Trigger中有:new,:old兩個(gè)特殊變量,當(dāng)觸發(fā)器為行級觸發(fā)器的時(shí)候,,觸發(fā)器就會提供new和old兩個(gè)保存臨時(shí)行數(shù)據(jù)的特殊變量,,我們可以從倆個(gè)特殊的變量中取出數(shù)據(jù)執(zhí)行擴(kuò)張表的DML操作,。
SQL語句如下:
- create trigger iu_table
- after insert on tr_table
- for each row
- begin
- insert into ts_table(tab_id,tab_name) values(:new.tab_id,:new.tab_name);
- --這里需要注意,,要知道不同的觸發(fā)類型其特殊變量:new和:old保存的值的區(qū)別,。
- --commit; 注意使用方案二,這里不能顯示的進(jìn)行提交操作操作,,trigger中在沒有聲明自定義事務(wù)管理的時(shí)候,,不能執(zhí)行顯示提交。
- end iu_table;
|