今天有人在Q上问了我一个关于触发器顺序的问题,他建立了2个触发器,条件和类型都相同,执行的语句也大同小异,都是使用raise_application_error返回错误,不同的是返回内容。
create or replace trigger v_trigger_1
before
delete on t004
for each row
begin
if to_char(sysdate,'YYYY')='2011' then
if deleting then
raise_application_error(-20001,'v_trigger_1不允许删除.');
sys.dbms_system.ksdwrt(2,'v_trigger_3 fired!');
end if;
end if;
end;
/
create or replace trigger v_trigger_2
before
delete on t004
for each row
begin
if to_char(sysdate,'YYYY')='2011' then
if deleting then
raise_application_error(-20001,'v_trigger_2不允许删除.');
sys.dbms_system.ksdwrt(2,'v_trigger_3 fired!');
end if;
end if;
end;
/
但是发现执行触发器的顺序总是后建的那个触发,也就是返回'v_trigger_2不允许删除.'
查看Oracle Database SQL Reference关于CREATE TRIGGER的内容,发现如下内容:
You can create multiple triggers of the same type (BEFORE, AFTER, or INSTEAD OF) that fire for the same statement on the same table. The order in which Oracle Database fires these triggers is indeterminate. If your application requires that one trigger be fired before another of the same type for the same statement, then combine these triggers into a single trigger whose trigger action performs the trigger actions of the original triggers in the appropriate order.
如果触发类型相同,语句相同,表相同,那么触发器触发具有不确定性,建议将这些触发器集合到单触发器中。但是经过测试,确实每次都是后建立的触发器先触发
通过sys.dbms_system.ksdwrt将内容记录到alert log中,将raise_application_error删除。这样每个触发器都会触发,记录的顺序也是按从最后建立的到最早建立的顺序(我建立了4个同样的触发器,且还更改了创建顺序):
Thu Feb 24 14:09:29 2011
v_trigger_4 fired!
v_trigger_3 fired!
v_trigger_2 fired!
v_trigger_1 fired!
Thu Feb 24 14:10:43 2011
v_trigger_3 fired!
v_trigger_4 fired!
v_trigger_2 fired!
v_trigger_1 fired!
之所以一开始触发器只触发一次,并且没有记录到alert log中,是因为用了raise_application_error,oracle就会终止当前执行,也就没有之后执行内容了。
注:对于非sys用户要执行SYS.DBMS_SYSTEM包内容,要分配execute权限给用户。
grant execute on SYS.DBMS_SYSTEM to ldy;
阅读(1011) | 评论(2) | 转发(0) |