1

トリガーを使用して、テーブルで更新が実行されたときに少なくとも 1 つの値が変更されたかどうかを検出します。

関数 :

CREATE OR REPLACE FUNCTION update_version_column()
  RETURNS trigger AS
$BODY$
BEGIN
    IF row(NEW.*) IS DISTINCT FROM row(OLD.*) THEN
        NEW.version = now(); 
        RETURN NEW;
    ELSE
        RETURN OLD;
    END IF;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION update_version_column()
  OWNER TO gamesplateform;

問題は、列タイプが「json」の場合、「is distinct」が失敗したことです (ドキュメントで説明されている標準的なコンポートメント)。

同じことを実行する方法を検索しますが、列が「json」タイプの場合、比較演算子を受け入れる「jsonb」キャストを強制したいと思います。

これを行う方法はありますか?

ありがとう !

4

1 に答える 1

0

これを行う方法を見つけました:

CREATE OR REPLACE FUNCTION update_version_column()
  RETURNS trigger AS
$BODY$

DECLARE
    updated boolean := false;
    column_data record;

BEGIN

    FOR column_data IN 
        SELECT
        column_name::varchar,
        data_type::varchar
        FROM information_schema.columns AS c
        WHERE table_name = TG_TABLE_NAME
    LOOP
        IF column_data.data_type = 'json' THEN
            EXECUTE format('SELECT CASE WHEN ($1).' || column_data.column_name || '::text <> ($2).' || column_data.column_name || '::text THEN true ELSE false END') 
            USING NEW, OLD
            INTO updated;
        ELSE
            EXECUTE format('SELECT CASE WHEN ($1).' || column_data.column_name || ' <> ($2).' || column_data.column_name || ' THEN true ELSE false END')
            USING NEW, OLD
            INTO updated;
        END IF;
        IF updated = true THEN
            NEW.version := now();
            RETURN NEW;
        END IF;
    END LOOP;

    RETURN OLD;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION update_version_column()
  OWNER TO gamesplateform;

「jsonb」で失敗したため(タイプが存在しません)、「json」を「text」にキャストしました。私の構成に固有のようですが、このトリガーは素晴らしい答えです:)

ありがとう@Julien Bossart !

于 2014-11-19T14:02:16.423 に答える