2013-02-27 22 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以任何方式發生了變化,或者您插入了一個新的行,我假設您只想記錄日誌。