假设我有下表:
CREATE TABLE data (
key TEXT primary key,
some_interesting_value TEXT,
inserted TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
updated TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
last_seen TIMESTAMP WITH TIME ZONE
);
然后我可以创建一个触发器来设置“更新”列,如下所示:
CREATE TRIGGER set_updated_col
AFTER UPDATE ON data
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE PROCEDURE set_updated_timestamp();
本last_seen
例中的列包含一个时间戳,每次运行进程(在某些条件下)时都会更新该时间戳。但是,这个值对于跟踪表更新没有意义。就我而言,我有很多这样的表。它们都包含有关物理网络设备的信息,并且“last_seen”值对每个实体都很重要。
即使只有“last_seen”值被修改,上面的触发器也会设置“updated”时间戳。
就我而言,我想避免这种情况。
我可以手动命名子句中的所有列WHEN
,但是,如果我向表中添加一列,则有可能会在他的触发器中忘记它。
有没有办法从中“删除”last_seen
列OLD.*
?
作为代码示例:
-- This should NOT trigger a change to `updated`
UPDATE data SET last_seen=NOW() WHERE key='foobar';
-- this SHOULD trigger a change to `updated`
UPDATE data SET some_interesting_value='foo', last_seen=NOW() WHERE key='foobar'
我不确定对性能的影响,但您可以将行转换为 jasonb、删除字段并比较 json 对象。
因此,更改
WHEN (OLD.* IS DISTINCT FROM NEW.*)
为when (row_to_json(old)::jsonb - 'last_seen' is distinct from row_to_json(new)::jsonb - 'last_seen')
将完成工作。还有,如果要修改
NEW.updated
,应该是BEFORE UPDATE
trigger,不是AFTER UPDATE
。