最近已經做好很久的已經很久的專案有個新需求,a表資源是歸屬於b表,所以a中有引用b表的bid。且b表中有個字段用於統計隸屬於他的a資源。當b表中某個資源更換他的隸屬關係是,則這個資源原隸屬的b資源統計字段需要重新計算。 a表
xtbh
bidacd
status12
101422
131432
20943
34 b表
xtbh
bcdstatus223
1433414
馬上想到觸發器於是
create or replace trigger insert_update_acd_tri
after
insert or update of acd,status
or delete on table_a
for each row
declare
yxtcd number;
xxtcd number;
begin
--如果原bid不為空,則重新計算原歸屬系統長度
if :old.bid is not null then
select sum(acd)
into yxtcd
from table_a q
where q.bid= :old.bid
and (q.status is null or q.status !='9');
update table_b bcd=yxtcd where xtbh=:old.bid;
end if;
--重新計算新歸屬系統長度
if :new.bid is not null then
select sum(acd)
into xxtcd
from table_a q
where q.bid= :new.bid
and (q.status is null or q.status !='9');
update table_b bcd=yxtcd where xtbh=:new.bid;
end if;
end insert_update_acd_tri;
寫完之後就在思考,更新a表的bid是會觸發該觸發器,但是現在更新事件的事物還未提交,而觸發器中又得查詢整個a表找出bid一直的記錄,並且重新統計acd的和,以更新b表中該bid的bcd。不知道此事觸發器執行時,a表是更新過呢,還是更新前的,更新過那麼重新查詢sum(acd)得到的才是正確的值。但是考慮到觸發器和觸發事件是同一事物空值,由於事物的特性,那麼我是after觸發器,所以觸發器執行的時候應該資料已經更新過。隨建立觸發器,並更新a表中一條資料的bid,結果出現
ora-04091
錯誤,原來它並沒有理會我是不是after觸發器,只要觸發事件和觸發器內容中對同一表或資料進行操作,你就得明確觸發器中使用的是更新前的還是更新後的資料。解決辦法有兩個
一,給觸發器加上自己的事物控制,不讓它和觸發事件同事物,即在觸發器的申明階段加上pragmaautonomous_transaction;但是別忘了既然自己控制事物,那麼觸發器end前一定要加上commit。
二,在有些情況,可以明確使用的是old值還是new值,但是這種方法有時候不好用,例如我這裡,
select sum(acd)
into yxtcd
from table_a q
where q.bid= :old.bid
and (q.status is null or q.status !='9');
select sum(acd)
into xxtcd
from table_a q
where q.bid= :new.bid
and (q.status is null or q.status !='9');
重新計算原歸屬系統及新歸屬系統的bcd,這裡已經明確使用new,old、了還是不行,原因是前面
from table_a q
where q.bid=
這裡的bid是指全表的qid欄位,而new,old只是當前資料行的新值舊值。
Oracle中的觸發器
oracle 中的觸發器 在oracle 中,觸發器是一種特殊的子程式,它在插入 更新 刪除資料時自動執行。使用觸發器可以實現比較複雜的約束。pk fk uq ck df 都是單錶約束資料完整性。觸發器可以分為 insert 觸發器 update 觸發器 delete 觸發器。insert 觸發器在...
ORACLE觸發器 行級觸發器
行級觸發器 本章介紹行級觸發器機制。大部分例子以insert出發器給出,行級觸發器可從insert update delete語句觸發。1 介紹 觸發器是儲存在資料庫已編譯的儲存過程,使用的語言是pl sql,用編寫儲存過程一樣的方式編寫和編譯觸發器。下面在sql plus會話中建立和示例乙個簡單的...
Oracle觸發器介紹 行級觸發器
行級觸發器 本章介紹行級觸發器機制。大部分例子以insert出發器給出,行級觸發器可從insert update delete語句觸發。1 介紹 觸 髮器是儲存在資料庫已編譯的儲存過程,使用的語言是pl sql,用編寫儲存過程一樣的方式編寫和編譯觸發器。下面在sql plus會話中建立和示例一 個簡...