Oracle不同的表触发顺序

时间:2013-07-22 19:30:04

标签: oracle triggers

我有两个触发器: 其中之一:

create or replace
TRIGGER bl_process_type_updated
before update
ON bl
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN 
    :new.process_type := 'UPDATED';
EXCEPTION    
 WHEN OTHERS THEN  
 NULL; 
 END;

另一个:

create or replace
TRIGGER bl_process_type_deleted
after insert or update
ON ot
FOR EACH ROW
DECLARE
    building_id bl.bl_id%TYPE;
BEGIN 
   building_id := :new.bl_id ;
   if(:new.status = 'Sold' or :new.status = 'LeaseTerminated') then
      update bl set process_type='DELETED' where bl_id = building_id;
    end if;
 EXCEPTION    
 WHEN OTHERS THEN  
 NULL; 
 END;

两个触发器都更新了bl表的process_type列。如果我更新ot表,bl表的触发器最后触发,那么process_type的值是UPDATED但是我希望当更新或插入ot表时,ot表的触发器触发最后一次process_type值将被删除。

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:0)

您可以执行以下操作:

create or replace TRIGGER bl_process_type_updated
before update
ON bl
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN 
    if :new.process_type <> 'DELETED' then
        :new.process_type := 'UPDATED';
    end if;
EXCEPTION WHEN OTHERS THEN  
    NULL; 
END;

答案 1 :(得分:0)

我会从@ Thomas的解决方案开始,但基于您后续的评论,很明显目前您没有可靠的方法让bl表知道process_type是否应该设置为UPDATED或者留下DELETED。

因此,您可能需要构建一些方法ot可以告诉bl该行将被保留为DELETED。

首先,不要试图影响触发器触发的顺序 - 你只会让自己陷入困境。

一种选择是放弃完全使用触发器的想法 - 即创建一个执行插入和放大的API(PL / SQL包)。更新这些表,并处理您需要的后续逻辑。显然,您需要修改应用程序才能使用API​​。一个简单的方法就是将视图放在表格前面,同时使用“而不是触发器”来调用API。

另一种选择是在bl_process_type_updated触发器中放置一个条件,如果更新来自bl_process_type_deleted触发器,则将其关闭。交换机必须存在于数据库包中,例如:

CREATE OR REPLACE PACKAGE bl_trigger_pkg AS
  bl_trigger_enabled BOOLEAN := TRUE;
END;
/

create or replace
TRIGGER bl_process_type_updated
  before update
  ON bl
  REFERENCING NEW AS NEW OLD AS OLD
  FOR EACH ROW
BEGIN 
  IF bl_trigger_pkg.bl_trigger_enabled THEN
    :new.process_type := 'UPDATED';
  END IF;
END;

create or replace
TRIGGER bl_process_type_deleted
  after insert or update
  ON ot
  FOR EACH ROW
DECLARE
   building_id bl.bl_id%TYPE;
BEGIN 
   building_id := :new.bl_id ;
   if(:new.status = 'Sold' or :new.status = 'LeaseTerminated') then
      bl_trigger_pkg.bl_trigger_enabled := FALSE;
      update bl set process_type='DELETED' where bl_id = building_id;
      bl_trigger_pkg.bl_trigger_enabled := TRUE;
   end if;
END;

顺便说一下,你必须摆脱WHEN OTHERS THEN NULL;位。你永远不应该只隐藏所有例外。