【问题标题】:Detecting column changes in a postgres update trigger检测 postgres 更新触发器中的列更改
【发布时间】:2014-05-21 16:08:53
【问题描述】:

我有一个 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 不同之外,没有任何简单的方法可以做到这一点。这样做的不好的方法是在我的通知过程中对列名进行硬编码(脆弱,如果我更改我的架构等要更新的另一件事)。

我在编写 plpgsql 方面也没有深度,真的,所以我不知道去哪里寻求帮助。理想情况下,(如果没有我在文档中没有看到的 updated_columns 块变量),有一种方法可以在通知块中获取表的架构,而不会造成太严重的性能开销(因为这些表将得到更新公平一点)。

【问题讨论】:

    标签: sql postgresql plpgsql


    【解决方案1】:

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

    changes := hstore(NEW) - hstore(OLD);
    ...pg_notify(... changes::text ...)
    

    这比您想要的信息略多(包括新值)。如果您只想要密钥,可以使用akeys(changed)

    【讨论】:

    • 这太完美了——我做了 pg_notify ... hstore_to_json(hstore(NEW) - hstore(OLD)) ...,除了数组类型列的变化(它们被转换成字符串)外,它的效果很好在结果 json 中看起来像 Postgres 数组 "{1, 2, 3}" 而不是实际的 "val": [1, 2, 3] 家伙,但我可以在客户端处理它,因为它是一个解析问题.
    • 在 9.3 中有 json 类型,在 9.4 中加入了许多改进mrnts(截至目前为测试版)。值得一试。
    【解决方案2】:

    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

    【讨论】:

      【解决方案3】:

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

      请参阅我原来的StackOverflow post 并提供适当的示例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-08
        • 2020-05-16
        相关资源
        最近更新 更多