Sql 检测postgres更新触发器中的列更改

Sql 检测postgres更新触发器中的列更改,sql,postgresql,plpgsql,Sql,Postgresql,Plpgsql,我有一个postgres数据库,其中有几个表,我想在这些表上查看更新,如果有任何更新,我想触发一个“嘿,有什么改变了”的更新。这在基本情况下有效,但现在是改进的时候了 CREATE FUNCTION notify_update() RETURNS trigger AS $notifyfunction$ BEGIN PERFORM pg_notify('update_watchers', $${"event":"update", "type": "$$ || TG_TABLE_NAME

我有一个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();
(作为一个附带问题:如果有比触发器函数中的mess'o'$$更好/更简单的方法来json.stringify我的触发器结果,请告诉我。平衡引号并不有趣)

我要做的是在pg_notify调用中附加一个已更改列的列表。除了遍历表中的列并检查NEW.col是否与OLD.col不同之外,似乎没有任何简单的方法可以做到这一点。做这件事的坏方法是在我的notify过程中硬编码列名(易碎,如果我更改模式,另一件要更新的事情,等等)

我在编写plpgsql方面也做得不够深入,真的,所以我不确定在哪里寻求帮助。理想情况下,(如果没有我在文档中没有看到的更新的_columns块变量),有一种方法可以在通知块中获取表的模式,而不会造成太大的性能开销(因为这些表会得到相当程度的更新)

请仔细阅读分机。特别是,您可以从一行创建一个hstore,这意味着您可以执行以下操作:

changes := hstore(NEW) - hstore(OLD);
...pg_notify(... changes::text ...)
这比您想要的信息稍微多一些(包括新的值)。如果您只需要钥匙,可以使用akeys(已更改)。

我执行完全相同类型的通知,我循环遍历所有列,如下所示:

    for k in TD["new"]:
        if TD["old"][k] != TD["new"][k]:
            changed.append(k)
已更改。追加(k)生成我的通知字符串。在其他地方,我会进行一次监听,然后将结果发布/发布到web套接字客户端


-另一种方法是利用PostgreSQL最新版本中的JSON/JSONB函数。它的优点是可以处理任何可以转换为JSON对象的对象(行或任何其他结构化数据),而且您甚至不需要知道记录类型


请参阅我的原稿,并提供适当的示例。

这太完美了-我没有通知PGU。。。hstore_to_json(hstore(NEW)-hstore(OLD))…,除了数组类型列中的更改(它们被剪切成字符串,看起来像Postgres数组“{1,2,3}”,而不是实际的“val”):[1,2,3]结果json中的人,但我可以在客户端处理,因为这是一个解析问题。9.3中有json类型,9.4中有许多改进(目前为beta版)。值得一看。
    for k in TD["new"]:
        if TD["old"][k] != TD["new"][k]:
            changed.append(k)