2013-02-27 5 views
0

Я пытаюсь создать триггер в базе данных оракула, и у меня возникают проблемы с условием. Когда я пытаюсь использовать его я получаю «неверный оператор отношения»Могу ли я использовать или устанавливать значение Когда в триггер?

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

+0

создать или заменить TRIGGER SQLTEST.TRIGGER_TESTE ПОСЛЕ вставки или обновления ПО SQLDBA.VT_TABLE ДЛЯ КАЖДОЙ ROW КОГДА (ВСТАВКА ИЛИ 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 в VAR_FIELD_1 FROM dual; INSERT INTO VT_LOG_TABLE (FIELD_0, VAR_FIELD_1, FIELD_2, FIELD_3, FIELD_1, FIELD_4) ЗНАЧЕНИЯ (: NEW.FIELD_0, VAR_FIELD_1,: NEW.FIELD_2,: NEW.FIELD_3,: NEW.FIELD_1, SYSDATE); END TRIGGER_TESTE; – Igor

+1

Ошибка может быть 'NEW.FIELD_1 <> OLD.FIELD_1', потому что при вставке у вас нет OLD для сравнения ... но не на 100% уверен в этом. – araknoid

ответ

2

Я просто попробовал нечто подобное, и Oracle не нравится значение INSERTING в условии WHEN. Кажется, что ОК с NEW и OLD, даже если вставка.

Из экспериментов, это выглядит как триггер будет срабатывать на вставках, если добавить к вашему при выполнении условия:

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 

Если это становится слишком сложным , вы можете создать два триггера: один для UPDATE с условием WHEN и один для INSERT без условий.

Вы также можете попробовать определения триггер AFTER INSERT или обновление Field_1 ПО 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 равно null» означает, что im вставляет новую строку, правильно? – Igor

+0

Действительно ли это правильный вывод? «NEW.FIELD_1 is null» предполагает, что поле имеет значение NULL.Если он равен нулю, и вы установили его не-null, он загорится, который, я думаю, вы хотите, хотя это не рассматривается в вопросе; но если оно равно null, и вы оставите его null при обновлении других полей, оно также будет срабатывать, не так ли? –

+1

Хороший вопрос Алекс. @Igor: мне просто пришло в голову, что вы также можете попробовать определить триггер как 'ПОСЛЕ ВСТАВКИ ИЛИ ОБНОВЛЕНИЯ Field_1 ON VT_TABLE'. Раньше я не использовал этот тип определения, но если я буду читать документы, он будет запускать (1) любой INSERT и (2) в любом UPDATE, который изменит Field_1. Я немного надавил на время, поэтому мне придется оставить его для экспериментов, если вы считаете, что этот подход стоит попробовать. –

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 изменился от null, до null или от одного ненулевого значения до другого; может быть, вы этого не хотите, частичная проверка выглядела немного странно. Я предполагаю, что вы хотите регистрироваться только в том случае, если field_1 каким-либо образом изменился, или если вы вставляете новую строку, конечно.

Смежные вопросы