2017-09-01 27 views
0

我是PL/SQL的新手,我試圖通過觸發器進行相當複雜的數據完整性檢查。在INSTERT或UPDATE上的PL/SQL觸發:「:NEW」是NULL =>模棱兩可?

我已經明白如何避免出現問題調用是在同一個表使用觸發器內表時(通過一個臨時的外部表),但我現在面臨一個非常令人興奮的問題:我認爲, ":NEW"被引用值在我的表AFTER的更新,但事情並沒有看上去那麼簡單......它被更新爲新值SET或插入... ...這看起來是NULL如果已指定什麼,即使更新後相應的字段值爲NOT NULL ......這讓我瘋狂。

我的觸發設置在插入或更新幾個變量時:

CREATE OR REPLACE TRIGGER TRG_INS_UP_INSTRUMENT_EVENT 
AFTER INSERT OR UPDATE OF EVENT_ID, DATE_BEGIN,DATE_END,INSTR_ID,TYPE_EVENT_ID ON AIS_INSTRUMENT_EVENT 

但是現在......如果已經有與非空字段行,我做了一個

UPDATE AIS_INSTRUMENT_EVENT SET INSTR_ID='642' WHERE EVENT_ID='6479' 

我實際上得到一個":NEW.DATE_BEGIN"這是NULL ...事件認爲也不是舊的或新的值是NULL(因爲我只是沒有更新它)。

我如何能夠區分 - 在我的觸發 - 在沒有新規定的情況下,當DATE_BEGIN被更新的情況下,並SET自願NULL(因此該字段必須保持不變,但不一定空... )。我有許多可能的組合,逐一檢查...

預先感謝您的幫助!

+0

如果你可以提供一個完整的測試用例(例如你的表格和觸發器的DDL以及輸入數據和預期輸出),它將會有所幫助;注意:這不需要成爲你的確切表格(例如,我們不關心列/表格/觸發器被稱爲什麼),但它確實需要重現你試圖解決的問題)。是什麼讓你認爲':new'值爲空? – Boneist

回答

1

你說的是不是事實。新的包含了完整的行而不管是否列在UPDATE語句引用:

CREATE TABLE test (test INTEGER, last_changed DATE); 

CREATE OR REPLACE TRIGGER TRG_INS_UP_TEST 
AFTER INSERT OR UPDATE OF test, last_changed ON test 
FOR EACH ROW 
BEGIN 
dbms_output.put_line('LAST CHANGED IS ' || :new.last_changed); 
END; 

INSERT INTO test (test, last_changed) VALUES (1, SYSDATE); 

COMMIT; 

UPDATE test SET test = test + 1; 

DBMS輸出:

LAST CHANGED IS 01.09.17 

達到你想要什麼樣的機制運行略有不同。你要看看在兩個不同的使用情況:

1)你想觸發不火,除非某列被提及。此用例由觸發器聲明中的引用(INSERT OR UDATE OF「column_name」)引用。如果INSERT/UPDATE語句僅影響未提及的列,則觸發器不會觸發。

2)你想觸發不火,除非某行被修改。因此,只有當fire是一個實際已經改變的值時,才需要觸發器。這是由WHEN限制觸發器完成的。它通常是配合使用DECODE,就像這樣:

CREATE OR REPLACE TRIGGER TRG_INS_UP_TEST 
AFTER INSERT OR UPDATE OF test, last_changed ON test 
FOR EACH ROW 
WHEN (DECODE(new.test,old.test,0,1)=1 OR DECODE(new. last_changed,old. last_changed,0,1)=1) 
BEGIN 
    ... 
END; 

因此,要回答你原來的問題:如果你想在列DATE_BEGIN設置爲NULL,你將不得不宣佈的情況下觸發也只火使用這兩種方法的觸發

CREATE OR REPLACE TRIGGER TRG_INS_UP_INSTRUMENT_EVENT 
AFTER INSERT OR UPDATE OF DATE_BEGIN ON AIS_INSTRUMENT_EVENT 
FOR EACH ROW 
WHEN (DECODE(new.DATE_BEGIN,old. DATE_BEGIN,0,1)=1 AND new.DATE_BEGIN IS NULL) 

的限制某些列(「插入或DATE_BEGIN OF UPDATE」)是不是絕對必要的,但它是很好的做法,因爲它可以提高性能,因爲它從發射都排除了扳機。

0

對不起,我認爲我做了一個快速的結論...錯誤是我的。我已經在「玩具」表上進行了測試,實際上,即使未由UPDATE設置,NEW也不爲null。在此期間我發現了這個錯誤。所有這些對我來說都太新了;-)。

對不起。