为 postgresql 中的每个更新行调用一个函数

Tim*_*Tim 5 postgresql function plpgsql sql-update

UPDATE我在 plpgsql 函数中有一条 sql语句。我现在想为每个更新的行调用 pg_notify 函数,并且不确定我的解决方案是否是最佳可能性。

我不知道UPDATE语句本身中有任何位置可以应用该函数。我认为这在该部分中是不可能的SET,如果我在该部分中应用该函数WHERE,它将应用于检查时的每一行,而不仅仅是更新的行,对吗?

因此,我认为我可以使用该RETURNING部分来达到我的目的,并设计了如下功能:

CREATE OR REPLACE FUNCTION function_name() RETURNS VOID AS $BODY$
BEGIN
    UPDATE table1
    SET a = TRUE
    FROM table2
    WHERE table1.b = table2.c
    AND <more conditions>
    RETURNING pg_notify('notification_name', table1.pk);
END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE;
Run Code Online (Sandbox Code Playgroud)

不幸的是,这给了我一个错误,说我没有在任何地方使用或存储查询的返回值。因此,我尝试将其放在PERFORM查询前面,但这在语法上似乎不正确。

在尝试了不同的组合后,PERFORM我的最终解决方案是这样的:

CREATE OR REPLACE FUNCTION function_name() RETURNS VOID AS $BODY$
DECLARE
    dev_null INTEGER;
BEGIN
    WITH updated AS (
        UPDATE table1
        SET a = TRUE
        FROM table2
        WHERE table1.b = table2.c
        AND <more conditions>
        RETURNING pg_notify('notification_name', table1.pk)
    )
    SELECT 1 INTO dev_null;

END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE;
Run Code Online (Sandbox Code Playgroud)

这按预期工作,但我觉得应该有一个更好的解决方案,它不会暂时存储无用的结果,也不会使用无用的变量。

感谢您的帮助。

** 编辑 1 **

正如@pnorton 的回答所示,在大多数情况下,触发器就可以解决问题。然而,对我来说,它不适用,因为通知的接收者有时也会更新表,并且我不想在这种情况下生成通知

小智 1

“我在 plpgsql 函数中有一个 sql UPDATE 语句。我现在想为每个更新的行调用 pg_notify 函数

好吧,我可能会想使用触发器,例如

    CREATE TABLE foobar (id serial primary key, name varchar);

CREATE OR REPLACE FUNCTION notify_trigger() RETURNS trigger AS $$
DECLARE
BEGIN
  PERFORM pg_notify('watch_tb_update', TG_TABLE_NAME || ',id,' || NEW.id );
  RETURN new;
END;
$$ LANGUAGE plpgsql;

CREATE  TRIGGER foobar_trigger AFTER INSERT ON foobar
FOR EACH ROW EXECUTE PROCEDURE notify_trigger();

LISTEN watch_tb_update;

INSERT into foobar(id, name) values(1,'test_name');
Run Code Online (Sandbox Code Playgroud)

我已经测试过了,效果很好