2017-09-01 12 views
0

私はPL/SQLの初心者です。私は、トリガーを介して非常に複雑なデータ整合性チェックをしようとしています。INSTERTまたはUPDATEのPL/SQLトリガー: ":NEW" IS 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 

しかし、今はすでに、私はそこにnull以外のフィールドを持つ行であると私は

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

をすれば...実際には":NEW.DATE_BEGIN"となります。これはNULL ...というイベントも考えられませんし、古い値や新しい値はNULLです(私はそれを更新しなかっただけなので)。

はどのようにして区別することができます - 私の引き金に - DATE_BEGINが何も指定されていない(このフィールドは、このように同じまま必ずしも必要ではないがNULL必要があるケースからNULLに更新し、SET自主的な場合を... )。私は一つ一つをチェックするために多くの可能な組み合わせにしなければならない...

あなたの助けを前もってありがとう!

+0

これは、実行しようとしていること(つまり、テーブルとトリガーのDDL、入力データと期待される出力の完全なテストケース)を提供できる場合に役立ちます.NBこれはあなたの正確なテーブル(例えば、カラム/テーブル/トリガが呼び出されているかどうかは気にしませんが、解決しようとしている問題を再現する必要があります)。 ':new'値がnullであると考えさせているのは何ですか? – 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. 2つの異なるユースケースを調べる必要があります。1.特定の列が記述されていない限り、トリガーは起動しません。この使用例は、トリガー宣言(INSERT OR UDATE OF "column_name")の参照によるものです。 INSERT/UPDATEステートメントが列に影響を与えない場合は、トリガーは起動しません。

2.)特定の行が変更されない限り、トリガーは起動しません。したがって、火災が実際に値が変更された場合に限り、トリガを欲しがります。これは、トリガのWHEN制限によって行われます。あなたがトリガーにしたい場合は、列DATE_BEGINがあなたをNULLに設定されている場合は、あまりにも唯一の火が宣言する必要があります。

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; 

だからあなたの元の質問に答えるために:そのようにこれは通常、DECODEと組み合わせて使用​​されていますあなたのトリガが特定の列(「INSERT OR DATE_BEGIN OF UPDATE」)に

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) 

制限を使用して、両方のアプローチは必須ではありませんが、それがすべてで発射からトリガを除外するので、それはパフォーマンスが向上するので、それは良い習慣です。

0

申し訳ありませんが、私はすぐに結論を下したと思います...このバグは私のものでした。私は "おもちゃ"のテーブルをテストしました。確かに:NEWはUPDATEによって設定されていなくてもnullではありませんでした。その間にバグが見つかりました。すべてこれは私にはあまりにも新しい;-)です。

申し訳ありません。

関連する問題