自治事務觸發器問題解答

 
環境:
一個數據庫下有兩個用戶一個爲smis一個爲yz,yz用戶只有查詢smis用戶表的權限。所有的操作都在smis用戶下,使用的數據庫爲Oracle9i。
在smis用戶下有表:
create table SONG_TEST
(
 ZXZT CHAR(1),
 ID   VARCHAR2(10)
)
yz用戶下有表:
create table T_SONG_TEST
(
 ZXZT CHAR(2),
 ID   VARCHAR2(10)
)
yz用戶下有觸發器:
create or replace trigger TRI_SONG_IN
    after insert on smis.SONG_TEST 
    for each row
declare
begin
insert into t_song_test(id,song)values(:new.id, :new.zxzt);
end TRI_SONG_IN;
1              爲什麼在smis用戶下插入數據時沒有提交而yz用戶表中卻有數據?
這是因爲在目錄的觸發器中使用的是自治事務觸發器,這種觸發器使得觸發的操作和目錄的操作不在同一個事物中。
經過測試沒有使用自治事務在沒有提交數據前,對比表中沒有數據。而使用了自治事務觸發器則在沒有提交數據前,yz用戶表中已經存在了數據。
自治事物觸發器的聲明爲,在declare內加入:
pragma   autonomous_transaction
觸發器爲:
create or replace trigger TRI_SONG_IN
    after insert on smis.SONG_TEST 
    for each row
declare
pragma   autonomous_transaction
begin
insert into t_song_test(id,song)values(:new.id, :new.zxzt);
commit;
end TRI_SONG_IN;
2              如果smis用戶的zxzt字段小於yz用戶表中的zxzt字段,能插進去數據嗎?
經過測試smis用戶的zxzt字段爲char(5),而yz用戶表中的zxzt字段爲char(1),在這種情況下插入數據,
例如:
insert into song_test(id,zxzt)values('1','22222')
則出現的結果是:
ORA-01401: 插入的值對於列過大
ORA-06512: 在"YZ.TRI_SONG_IN", line 5
ORA-04088: 觸發器 'YZ.TRI_SONG_IN' 執行過程中出錯
這樣在smis用戶和yz用戶表中都沒有插入數據。因爲觸發器出錯會向上拋出異常,最後由PL/SQL處理,將整個事物回滾。
3              如果用自治事物觸發器去查找臨時表中的數據,然後插入yz用戶表。如果沒有查找到數據會怎樣?
經過測試如果沒有找到數據則會出現以下信息:
ORA-01403: 未找到數據
ORA-06512: 在"YZ.TRI_CQZ_GJHZW_IN", line 6
ORA-04088: 觸發器 'YZ.TRI_CQZ_GJHZW_IN' 執行過程中出錯
這樣其所做的操作也一起回滾。因爲觸發器出錯會向上拋出異常,最後由PL/SQL處理,將整個事物回滾。
4              觸發器中的變量如果定義過大,會怎樣?
觸發器寫法如下:
create or replace trigger TRI_SONG_IN
   after insert on smis.SONG_TEST 
   for each row
    declare
   str char(10);
   pragma   autonomous_transaction;
    begin
    str:='1';
    insert into t_song_test(id,zxzt)values(:new.id,str);
    commit;
    end TRI_SONG_IN;
其中zxzt的字段大小爲char(2),執行以下操作:
insert into song_test(id,zxzt)values('1','2')
則會出現以下信息:
ORA-01401: 插入的值對於列過大
ORA-06512: 在"YZ.TRI_SONG_IN", line 7
ORA-04088: 觸發器 'YZ.TRI_SONG_IN' 執行過程中出錯
這時smis中的表和對比表中都沒有數據。因爲觸發器出錯會向上拋出異常,最後由PL/SQL處理,將整個事物回滾。
5              自治事務觸發器和相對應的操作是否在一個事物中?
在第四問中大家將要問到爲什麼smis表中都沒有數據,他們的事務不是分開的嗎?
我們現在來改寫以下觸發器:
create or replace trigger TRI_SONG_IN
   after insert on smis.SONG_TEST 
   for each row
    declare
   str char(10);
   pragma   autonomous_transaction;
    begin
    str:='1';
    insert into t_song_test(id,zxzt)values(:new.id,str);
    commit;
exception
   when others then
   rollback;
   end TRI_SONG_IN;
在這裏我們加入了對異常的捕獲和處理然後在執行插入操作:
insert into song_test(id,zxzt)values('1','2')
並提交,這樣則會正確執行。而且smis的表中也有相應的數據插入。但在yz用戶表中卻沒有數據。通過分析得知原來是異常惹得禍,在觸發器中如果沒有捕獲和處理異常,觸發器就會在運行時自動拋出,執行部分拋出的異常將首先傳遞到同一塊的異常部分,如果在同一塊的異常部分沒有處理這個異常的處理器,那麼異常將會傳播到上一層的異常部分中,一直到最外層。當異常到最外層時PL/SQL就將整個事務回滾。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章