2013-02-27 1 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

전체 트리거를 게시 할 수 있습니까? (넣거나 NEW.FIELD_1가 null OLD.FIELD_1가 NEW.FIELD_1 <> OLD.FIELD_1 널 없거나) WHEN – araknoid

+0

생성하거나 EACH ROW FOR SQLDBA.VT_TABLE ON INSERT OR UPDATE 후에 트리거 SQLTEST.TRIGGER_TESTE 대체 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

+1

삽입 할 때 OLD를 비교할 수 없기 때문에 오류가 'NEW.FIELD_1 <> OLD.FIELD_1'일 수 있습니다. 그러나 이것에 대해서는 100 % 확신 할 수 없습니다. – araknoid

답변

2

나는 비슷한 것을 시도했으며 Oracle은 WHEN 조건에서 INSERTING 값을 좋아하지 않습니다. 삽입하는 경우에도 NEW와 OLD는 괜찮을 것으로 보입니다. 즉 너무 복잡해진다 경우

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 

:

OR OLD.FIELD_1 IS NULL 

그래서 이런 식으로 뭔가를 시도 : 실험에서

, 그것은 당신이 언제 조건이 추가하면 트리거가 인서트에 발생합니다 같습니다 WHEN 조건을 갖는 UPDATE와 조건없이 INSERT를위한 두 개의 트리거를 생성 할 수 있습니다.

또한 Field_1 ON VT_TABLE의 INSERT 또는 UPDATE AFTER으로 방아쇠를 정의하는 시도 할 수 : graceemile 말하는 것처럼, WHEN 절은 INSERTING을 이해하지 못하는

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"이면 새 행을 삽입하는 것입니다. 맞습니까? – Igor

+0

그게 유익한 추론입니까? 'NEW.FIELD_1 is null'은 필드가 null을 허용한다는 것을 나타냅니다.그것이 null이며 null이 아닌 것으로 설정하면 화재가 발생합니다. 원하는 것으로 생각됩니다. 하지만 null이고 다른 필드를 업데이트하는 동안 null로두면 화재가 발생합니다. 그렇습니까? –

+1

좋은 점 알렉스. @Igor : 방금 당신이 트리거를 'AFTER INSERT 또는 UPDATE OF Field_1 ON VT_TABLE'으로 정의 할 수 있다는 생각이 들었습니다. 이전에이 유형의 정의를 사용하지 않았지만, 문서를 올바르게 읽는다면 Field_1을 변경하는 UPDATE에 INSERT 및 (2)를 실행합니다. 나는이 접근법이 노력할만한 가치가 있다고 생각한다면 실험을 위해 당신에게 맡겨야 할 것입니다. –

3

. 난 old.field_1 is null에 nullable 필드처럼 보이기 때문에 삽입을 나타낼 수 있는지 확신 할 수 없습니다 (new.field_1이 분명히 null 일 수 있기 때문에). 당신은 당신이 단지 블록으로 논리를 움직일 수없는 경우 : field_1가 변경되었는지 감지 ...

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) 

: 내가 변경 한

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; 
/

은이에 비트를 확인 널 (null)에서 널 (null)로 또는 널이 아닌 값에서 다른 값으로; 어쩌면 당신은 그것을 원하지 않을 것입니다, 부분 검사는 저에게 약간 이상하게 보였습니다. field_1이 어떤 식 으로든 변경되었거나 물론 새로운 행을 삽입하는 경우에만 로그하려는 것으로 가정합니다.

관련 문제