2016-09-21 5 views
0

私の顧客テーブルに次のトリガがあるので、時間の経過とともに顧客名が変更されたかどうか、以前のバージョンの名前がどのようなものかを確認できます。NEW.fieldがNULLのときにPostgreSQLが起動しない

CREATE OR REPLACE FUNCTION fn_customer_changes_log_history() RETURNS trigger as 
$BODY$ 
    BEGIN 
     IF (NEW.name <> OLD.name) 
    THEN 
     INSERT INTO tbl_customers_history(customer_id, name, action) 
     VALUES(OLD.id, OLD.name, 'UPDATE'); 
    END IF; 
RETURN NEW; 
END; 
$BODY$ 
LANGUAGE plpgsql; 

CREATE TRIGGER tr_customer_changes_log_history 
BEFORE UPDATE ON tbl_customers 
FOR EACH ROW 
EXECUTE PROCEDURE fn_customer_changes_log_history(); 

しかし、私はUPDATEを行う際際NEW.name = NULLとし、OLD.name =「お客様1」は、このトリガーは起動されませんか?これは、NEW.nameが実際の文字列値を持つ場合にのみトリガされます。

なぜですか? NULLと "Customer 1"は等しくないのでトリガする必要がありますか?

答えて

1

は、問題がNEW.fieldNULLであるならば、NEW.name <> OLD.nameは関係なくOLD.nameの値が何であるかNULLに評価されないということである

IF COALESCE((NEW.name <> OLD.name), true) 

に条件を変更してみてください。条件付きでは、NULLは常にfalseとして扱われます。

より正しい答えは、彼らが、その場合には同じものとして扱われないようNEW.nameOLD.nameの両方が、NULLあるときにケースの世話をするために

IF COALESCE((NEW.name <> OLD.name), true) AND NOT (NEW.name IS NULL AND OLD.name IS NULL) 

されていると思います。

+0

ありがとう:

あなたが比較を修正する​​3210を必要としています。これは機能します。しかし、なぜ私がしたようにそれが引き起こされないか、あなたは何か考えがありますか?なぜこのCOALESCEものが必要なのですか? – koala

+1

@koala私は自分の答えを広げました。 – redneb

0

NULL <> 'anything'は、常にFALSEと評価されます。ちょうどNULL = 'anything'またはNULL > 5のように。

COALESCE(NEW.name, '') <> COALESCE(OLD.name, '') 
2

使用

IF (NEW.name IS DISTINCT FROM OLD.name) 

代わりの

IF (NEW.name <> OLD.name) 
+0

これをCOALESCEの提案された回答と比較すると、これはどのように機能しますか? – koala

+0

少々操作が少なくなるかもしれませんが、測定可能な差はないと思います。私は読むのが簡単なので私のバージョンを好むだろう。 –

関連する問題