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;

我将“json”转换为“text”,因为“jsonb”失败(类型不存在)。似乎特定于我的配置,但这个触发器的答案很好:)

谢谢@Julien Bossart!

于 2014-11-19T14:02:16.423 回答