我有一个postgres数据库,其中包含几个我想要查看更新的表格,如果有任何更新,我想要点击“嘿,改变了一些”更新。这适用于基本情况,但现在是时候改进了。
CREATE FUNCTION notify_update() RETURNS trigger AS $notifyfunction$
BEGIN
PERFORM pg_notify('update_watchers',
$${"event":"update", "type": "$$ || TG_TABLE_NAME || $$", "payload": {"id": $$ || new.id || $$}}$$);
RETURN new;
END;
$notifyfunction$ LANGUAGE plpgsql;
工作得很好。我把它像这样附在桌子上:
CREATE TRIGGER document_update_body
AFTER UPDATE ON documents
FOR EACH ROW EXECUTE PROCEDURE notify_update();
(作为一个侧面问题:如果json.stringify我的触发结果比触发器功能中的mess'o' $$更好/更简单,请告诉我。平衡引号并不好玩)
我想要做的是在pg_notify调用中附加已更改的列的列表。除了迭代表中的列并检查NEW.col是否与OLD.col不同之外,它不像似乎就像有任何简单的方法来做到这一点。执行此操作的不好方法是在我的通知过程中对列名进行硬编码(脆弱,如果我更改模式则更新另一件事等)。
我也非常喜欢编写plpgsql,所以我不确定在哪里寻求帮助。理想情况下(如果没有我在文档中没有看到的updated_columns块变量),有一种方法可以在通知块中获取表的模式,而不会导致过于严重的性能开销(因为这些表将更新为公平的)。
答案 0 :(得分:6)
阅读hstore扩展程序。特别是您可以从一行创建一个hstore,这意味着您可以执行以下操作:
changes := hstore(NEW) - hstore(OLD);
...pg_notify(... changes::text ...)
这比您想要的信息略多(包括新值)。如果您只想要密钥,可以使用akeys(changed)
。
答案 1 :(得分:1)
http://www.postgresql.org/docs/9.3/static/plpython-trigger.html
TD["table_name"]
我完全使用相同类型的通知,我遍历所有列,如下所示:
for k in TD["new"]:
if TD["old"][k] != TD["new"][k]:
changed.append(k)
changed.append(k)构建我的通知字符串。在其他地方我做一个监听,然后将结果从pub / sub广播到web套接字客户端。
-g
答案 2 :(得分:0)
另一种方法是利用PostgreSQL最新版本中的JSON / JSONB函数。它的优点是可以处理可转换为JSON对象(行或任何其他结构化数据)的任何内容,甚至不需要知道记录类型。
请参阅我的原始StackOverflow post和适当的示例。