2013-02-27 41 views
0

我想在oracle数据库上创建一个触发器,并且遇到了条件时的问题。 当我尝试使用它,我得到“无效的关系运算符”我可以使用或触发何时触发?

create or replace TRIGGER SQLTEST.TRIGGER_TESTE 
AFTER INSERT OR UPDATE ON SQLDBA.VT_TABLE 
FOR EACH ROW 
WHEN (INSERTING OR NEW.FIELD_1 is null and OLD.FIELD_1 is not null or NEW.FIELD_1 <> OLD.FIELD_1) 

DECLARE 
VAR_FIELD_1 VT_LOG_TABLE.FIELD_1%TYPE; 

BEGIN 

SELECT SQLDBA.SEQ_LOG_TABLE.NEXtval into VAR_FIELD_1 
FROM dual; 


INSERT INTO VT_LOG_TABLE 
(FIELD_0,VAR_FIELD_1,FIELD_2,FIELD_3,FIELD_1, FIELD_4) 
VALUES(:NEW.FIELD_0,VAR_FIELD_1, :NEW.FIELD_2, :NEW.FIELD_3, :NEW.FIELD_1,SYSDATE); 

END TRIGGER_TESTE; 

什么使这一条件的正确方法?

+0

你可以发布整个触发器吗? – araknoid 2013-02-27 18:37:12

+0

创建或替换TRIGGER SQLTEST.TRIGGER_TESTE 插入或更新后SQLDBA.VT_TABLE FOR EACH ROW WHEN(插入或NEW.FIELD_1为空和OLD.FIELD_1不为空或NEW.FIELD_1 <> OLD.FIELD_1) DECLARE VAR_FIELD_1 VT_LOG_TABLE.FIELD_1%TYPE; BEGIN SELECT SQLDBA.SEQ_LOG_TABLE.NEXtval into VAR_FIELD_1 FROM dual; INSERT INTO VT_LOG_TABLE (FIELD_0,VAR_FIELD_1,FIELD_2,FIELD_3,FIELD_1,FIELD_4) VALUES(:NEW.FIELD_0,VAR_FIELD_1,:NEW.FIELD_2,:NEW.FIELD_3,:NEW.FIELD_1,SYSDATE); END TRIGGER_TESTE; – Igor 2013-02-27 18:41:27

+1

错误可能是'NEW.FIELD_1 <> OLD.FIELD_1',因为插入时没有用于比较的OLD ...但不能100%确定这一点。 – araknoid 2013-02-27 18:49:56

回答

2

我刚刚尝试了类似的东西,Oracle在WHEN条件下不喜欢INSERTING值。即使插入,NEW和OLD似乎也没问题。

根据实验,它看起来像你的触发条件会在插入如果您添加到您的WHEN条件:

OR OLD.FIELD_1 IS NULL 

因此,尝试这样的事:

create or replace TRIGGER SQLTEST.TRIGGER_TESTE 
AFTER INSERT OR UPDATE ON SQLDBA.VT_TABLE 
FOR EACH ROW 
WHEN (NEW.FIELD_1 is null and OLD.FIELD_1 is not null 
    or NEW.FIELD_1 <> OLD.FIELD_1 
    or OLD.FIELD_1 IS NULL) 

DECLARE 

... and so on 

如果变得太复杂,您可以创建两个触发器:一个用于WHEN条件的UPDATE,一个用于INSERT,无条件。

您也可以尝试定义触发作为插入或更新Field_1 ON VT_TABLE后:

create or replace trigger vt_trigger 
after insert or update of field_1 on vt_table 
for each row 
begin 
    insert into vt_log_table (field_0, var_field_1, field_2, field_3, 
     field_1, field_4) 
    values (:new.field_0, seq_log_table.nextval, :new.field_2, :new.field_3, 
     :new.field_1, sysdate); 
end vt_trigger; 
/
+0

如果“OLD.FIELD_1为空”,这意味着即时通讯插入一个新的行,对吧? – Igor 2013-02-27 20:02:56

+0

这是一个有效的推论吗? 'NEW.FIELD_1为空'表示该字段可以为空。如果它是空的,并且你将它设置为非null,那么它会触发,我认为你想要的 - 尽管这不在问题中;但如果它为空,并且在更新其他字段时将其留空,则它也会启动,不是吗? – 2013-02-27 21:28:12

+1

好点Alex。 @Igor:我想到你也可以尝试将触发器定义为'AFTER INSERT或更新Field_1 ON VT_TABLE'。我之前没有使用过这种类型的定义,但是如果我正在阅读文档,它将触发(1)任何INSERT和(2)任何更新Field_1的UPDATE。我有点时间紧迫,所以如果你认为这种方法值得尝试,我必须让你试验一下。 – 2013-02-27 21:48:08

3

由于graceemile说,该WHEN条款不理解INSERTING。我不确定是否可以依靠old.field_1 is null来指示插入,因为它看起来像一个可为空的字段(因为new.field_1显然可以为空)。如果不能,那么你可以只移动逻辑成块:

create or replace trigger vt_trigger 
after insert or update on vt_table 
for each row 
declare 
    do_logging boolean := false; 
begin 
    if inserting then 
     do_logging := true; 
    elsif (:new.field_1 is null and :old.field_1 is not null) 
     or (:new.field_1 is not null and :old.field_1 is null) 
     or (:new.field_1 <> :old.field_1) 
    then 
     do_logging := true; 
    end if; 

    if do_logging then 
     insert into vt_log_table (field_0, var_field_1, field_2, field_3, 
      field_1, field_4) 
     values (:new.field_0, seq_log_table.nextval, :new.field_2, :new.field_3, 
      :new.field_1, sysdate); 
    end if; 
end vt_trigger; 
/

我已经改变了查了一下这个:

elsif (:new.field_1 is null and :old.field_1 is not null) 
     or (:new.field_1 is not null and :old.field_1 is null) 
     or (:new.field_1 <> :old.field_1) 

...检测是否已经field_1改变从空,到空,或从一个非空值到另一个;也许你不想那样,局部检查对我来说看起来有点奇怪。如果field_1以任何方式发生了变化,或者您插入了一个新的行,我假设您只想记录日志。