特定の1つの列の更新時にのみトリガーを起動するコードがあります。トリガーは、postgresの「通知」イベントを発生させる関数を起動するために使用されます。このイベントは、私がリッスンしていて、新しく入力された詳細をテストおよび検証する必要があります。 account_detailsテーブルには、アカウントの検証を必要としない変更可能な値が多数あるため、AFTER UPDATEのみのトリガー(whenなし)は適切ではありません。
CREATE TRIGGER trigger_update_account_details
AFTER UPDATE ON account_details
FOR EACH ROW
WHEN (OLD.email IS DISTINCT FROM NEW.email)
EXECUTE PROCEDURE notify_insert_account_details();
しかし、私は多くの列の1つが変更された場合にトリガーを起動したいと思います。
WHEN (OLD.email IS DISTINCT FROM NEW.email OR
OLD.username IS DISTINCT FROM NEW.username OR
OLD.password IS DISTINCT FROM NEW.password)
ただし、ORはトリガーに有効なキーワードではありません。ORの代わりに使用するキーワードを検索しようとしても、言葉の性質OR :-(
これは誤解です。トリガー定義の WHEN
句にはboolean
式 が必要であり、その中でOR
演算子を使用できます。これは機能するはずです(すべての列が実際にテーブルaccount_details
に存在する場合)。私自身も同様のトリガーを使用しています:
CREATE TRIGGER trigger_update_account_details
AFTER UPDATE ON account_details
FOR EACH ROW
WHEN (OLD.email IS DISTINCT FROM NEW.email
OR OLD.username IS DISTINCT FROM NEW.username
OR OLD.password IS DISTINCT FROM NEW.password)
EXECUTE PROCEDURE notify_insert_account_details();
式の評価にはわずかなコストがかかりますが、これはおそらく他の方法より信頼性が高いです。
CREATE TRIGGER ... AFTER UPDATE OF email, username, password ...
なぜなら、 ドキュメントごと :
列固有のトリガー(
UPDATE OF
column_name
を使用して定義されたトリガー)構文)は、その列のいずれかがUPDATE
コマンドのSET
リストにターゲットとしてリストされているときに起動します。BEFORE UPDATE
トリガーによって行の内容に加えられた変更は考慮されないため、トリガーが起動されていなくても、列の値が変更される可能性があります。逆に、列の値が変更されていなくても、UPDATE ... SET x = x ...
などのコマンドは列xでトリガーを起動します。
ROW
タイプ構文は多くの列をチェックするために短くなっています(同じことをしています):
CREATE TRIGGER trigger_update_account_details
AFTER UPDATE ON account_details
FOR EACH ROW
WHEN ((OLD.email, OLD.username, OLD.password, ...)
IS DISTINCT FROM
(NEW.email, NEW.username, NEW.password, ...))
EXECUTE PROCEDURE notify_insert_account_details();
または、行のevery表示されているユーザー列を確認するには:
...
WHEN (OLD IS DISTINCT FROM NEW)
...
WHEN
句は必要ないと思います。問題の列をUPDATE句で指定できます。
CREATE TRIGGER trigger_update_account_details
AFTER UPDATE OF email, username, password ON account_details
FOR EACH ROW
EXECUTE PROCEDURE notify_insert_account_details();
上記の解決策は私にとって適切に機能しませんでした。もう一度ドキュメントを読んだ後。注意すべきことがいくつか見つかりました。 BEFORE UPDATE ON-AFTER UPDATE ONトリガーの実行方法は異なります。私の手順では、更新された値でNEWレコードを返していました。 AFTERトリガーおよびBEFOREトリガーでは機能せず、WHEN句内のORステートメントを中括弧で囲む必要がありました。
CREATE TRIGGER check_update
BEFORE UPDATE ON some_table
FOR EACH ROW
WHEN ((OLD.colum_name_1 IS DISTINCT FROM NEW.colum_name_1) OR (OLD.colum_name_2 IS DISTINCT FROM NEW.colum_name_2))
EXECUTE PROCEDURE update_updated_at_column();
そして手順
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';