我在plpgsql函数中有一个sql UPDATE
语句。我现在想为每个更新的行调用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;
不幸的是,这给了我一个错误,说我没有在任何地方使用或存储查询的返回值。因此,我尝试将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;
这可以按预期工作,但我觉得应该有一个更好的解决方案,它不会暂时存储无用的结果,也不会使用无用的变量。
感谢您的帮助。
**编辑1 **
从@pnorton的回答可以看出,在大多数情况下,触发器可以解决问题。然而,对我来说,它不适用,因为通知的接收者有时也会更新表格,我不想在这种情况下生成通知
答案 0 :(得分:1)
&#34;我在plpgsql函数中有一个sql UPDATE语句。 我现在想要 为每个更新的行调用pg_notify函数&#34;
好的我可能想要使用触发器Eg
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');
我已经对此进行了测试,但效果很好