これは可能ですか?送信される新しい値が既にデータベースに格納されているものであるかどうかに関係なく、UPDATE
要求で指定された列を見つけることに興味があります。
これを行う理由は、複数のソースから更新を受信できるテーブルがあるためです。以前は、更新のソースを記録していませんでした。これで、テーブルには最新の更新を実行したソースが格納されます。一部のソースを変更してIDを送信できますが、それがすべてのオプションになるわけではありません。したがって、UPDATE
リクエストに識別子がない場合に認識できるようにして、デフォルト値で置き換えることができます。
「ソース」が「識別子を送信」しない場合、列は変更されません。次に、現在のUPDATE
が最後のソースと同じソースによって行われたのか、列をまったく変更しなかったソースによって行われたのかを検出できません。つまり、これは適切に機能しません。
「ソース」が任意の セッション情報関数 で識別可能であれば、それで作業できます。お気に入り:
_NEW.column = session_user;
_
すべての更新に対して無条件。
元の問題を解決する方法を見つけました。列はanyupdateでデフォルト値に設定されますが、列はnotupdate(SET
のUPDATE
リストにはありません)。
キー要素は per-column trigger PostgreSQL 9.0で導入されました-_UPDATE OF
_を使用した列固有のトリガー_column_name
_句。
トリガーは、リストされた列の少なくとも1つが
UPDATE
コマンドのターゲットとして言及されている場合にのみ起動します。
これが、列が古い値と同じ新しい値で更新されたか、まったく更新されなかったかを区別するために見つけた唯一の簡単な方法です。
1つcouldも current_query()
によって返されたテキストを解析します。しかし、それはトリッキーで信頼性が低いようです。
列col
が_NOT NULL
_を定義すると想定します。
ステップ1:変更されていない場合は、col
をNULL
に設定します。
_CREATE OR REPLACE FUNCTION trg_tbl_upbef_step1()
RETURNS trigger AS
$func$
BEGIN
IF OLD.col = NEW.col THEN
NEW.col := NULL; -- "impossible" value
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
_
ステップ2:古い値に戻します。トリガーは値が実際に更新された場合にのみ発生します(以下を参照):
_CREATE OR REPLACE FUNCTION trg_tbl_upbef_step2()
RETURNS trigger AS
$func$
BEGIN
IF NEW.col IS NULL THEN
NEW.col := OLD.col;
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
_
ステップ3:これで、不足している更新を識別し、代わりにデフォルト値を設定できます。
_CREATE OR REPLACE FUNCTION trg_tbl_upbef_step3()
RETURNS trigger AS
$func$
BEGIN
IF NEW.col IS NULL THEN
NEW.col := 'default value';
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
_
Step 2のトリガーは列ごとに発生します!
_CREATE TRIGGER upbef_step1
BEFORE UPDATE ON tbl
FOR EACH ROW
EXECUTE PROCEDURE trg_tbl_upbef_step1();
CREATE TRIGGER upbef_step2
BEFORE UPDATE OF col ON tbl -- key element!
FOR EACH ROW
EXECUTE PROCEDURE trg_tbl_upbef_step2();
CREATE TRIGGER upbef_step3
BEFORE UPDATE ON tbl
FOR EACH ROW
EXECUTE PROCEDURE trg_tbl_upbef_step3();
_
トリガー名は、アルファベット順に起動されるため、関連があります(すべて_BEFORE UPDATE
_です)!
手順は、「列ごとではないトリガー」のようなもの、またはトリガー内のUPDATE
のターゲットリストをチェックする他の方法で簡略化できます。しかし、私はこれに対応できません。
col
がNULL
の場合は、他の「不可能な」中間値を使用し、トリガー関数1でNULL
を追加でチェックします。
_IF OLD.col IS NOT DISTINCT FROM NEW.col THEN
NEW.col := '#impossible_value#';
END IF;
_
残りを適宜調整してください。
Plpgsqlでは、トリガー関数で次のようなことができます:
IF NEW.column IS NULL THEN
NEW.column = 'default value';
END IF;
私のテーブルには「最終更新タイムスタンプ」のセマンティクスを持つ列が含まれているため、ほぼ自然に同様の問題の別の解決策が得られました(これをUPDTと呼びます)。
そのため、更新にソースとUPDTの新しい値を一度に1つだけ含めるか、またはそれらに含めないことにしました。 UPDTは更新ごとに変更することを目的としているため、このようなポリシーを使用すると、条件new.UPDT = old.UPDT
を使用して、現在の更新でソースが指定されていないことを推定し、デフォルトの更新で置き換えることができます。
テーブルに「最終更新タイムスタンプ」列がすでにある場合、このソリューションは3つのトリガーを作成するよりも簡単です。 UPDTを作成する方が良いかどうか、まだ必要ない場合はわかりません。更新が頻繁でタイムスタンプの類似性のリスクがある場合は、タイムスタンプの代わりにシーケンサーを使用できます。