如何在 postgresql NOTIFY 消息中将列值作为有效负载发送?
How can I send column values as the payload in a postgresql NOTIFY message?
如果 table 中的条目满足特定条件,则会发出通知。我希望有效载荷包括 ID 号和其他几列信息。是否有将变量(OLD.ColumnID 等)转换为字符串的 postgres 方法?
使用 postgres 9.3
我的猜测是通知必须在触发器函数中完成。使用动态查询,例如
execute format('notify channel, ''id: %s''', old.id);
@klin 是正确的,NOTIFY
不支持除字符串文字以外的任何内容。然而,有一个函数 pg_notify() 接受普通参数来处理这种情况。它至少从 9.0 开始就存在,link 是官方文档 - 总是值得仔细阅读,那里有丰富的信息。
解决方案是将 Postgres 升级到支持 JSON 的版本。
甚至 postgresql 9.3 也支持 json。你可以使用 row_to_json(payload)::text
抱歉回答太长,我也不能不对其他答案做出反应就走开。
format
版本在很多方面都失败了。在执行之前,您应该准备好计划。 "pseudo command" 不符合 execute 的语法
EXECUTE somepreparedplanname (parameter1, ...)
%s 的格式又太糟糕了,这样你就可以召唤 sql 注入攻击。使用 format
构造查询时,您需要将 %L 用于 column/table/function/etc id 的文字 %I,并且几乎从不使用 %s。
另一个带有pg_notify
函数的解是正确的。尝试
LISTEN channel;
SELECT pg_notify('channel','Id: '|| pg_backend_pid ());
在 psql 命令行中。
所以回到最初的问题:sdemurjian,
如果您想在某些触发功能中使用此通知,问题中没有说明。所以这里有一个例子(也许不是)给你(因为我来晚了。对此也很抱歉):
CREATE TABLE columns("columnID" oid, "columnData" text);
CREATE FUNCTION column_trigger_func() RETURNS TRIGGER AS
$$ BEGIN PERFORM pg_notify('columnchannel', 'Id: '||OLD."columnID");
RETURN NEW; END; $$ LANGUAGE plpgsql;
CREATE TRIGGER column_notify BEFORE UPDATE ON columns FOR EACH ROW
EXECUTE PROCEDURE column_trigger_func();
LISTEN columnchannel;
INSERT INTO columns VALUES(1,'testdata');
BEGIN; UPDATE columns SET "columnData" = 'success'; END;
BEGIN; UPDATE columns SET "columnData" = 'fail'; ROLLBACK;
请注意,在早期的 postgres 版本(9 之前的任何版本)中,notify 命令不接受任何负载并且没有 pg_notify 函数。
在 8.1 中,如果您像
那样定义触发器函数,它仍然可以工作
CREATE FUNCTION column_trigger_func() RETURNS TRIGGER AS
$$ BEGIN NOTIFY columnchannel; RETURN NEW; END; $$ LANGUAGE plpgsql;
如果 table 中的条目满足特定条件,则会发出通知。我希望有效载荷包括 ID 号和其他几列信息。是否有将变量(OLD.ColumnID 等)转换为字符串的 postgres 方法?
使用 postgres 9.3
我的猜测是通知必须在触发器函数中完成。使用动态查询,例如
execute format('notify channel, ''id: %s''', old.id);
@klin 是正确的,NOTIFY
不支持除字符串文字以外的任何内容。然而,有一个函数 pg_notify() 接受普通参数来处理这种情况。它至少从 9.0 开始就存在,link 是官方文档 - 总是值得仔细阅读,那里有丰富的信息。
解决方案是将 Postgres 升级到支持 JSON 的版本。
甚至 postgresql 9.3 也支持 json。你可以使用 row_to_json(payload)::text
抱歉回答太长,我也不能不对其他答案做出反应就走开。
format
版本在很多方面都失败了。在执行之前,您应该准备好计划。 "pseudo command" 不符合 execute 的语法
EXECUTE somepreparedplanname (parameter1, ...)
%s 的格式又太糟糕了,这样你就可以召唤 sql 注入攻击。使用 format
构造查询时,您需要将 %L 用于 column/table/function/etc id 的文字 %I,并且几乎从不使用 %s。
另一个带有pg_notify
函数的解是正确的。尝试
LISTEN channel;
SELECT pg_notify('channel','Id: '|| pg_backend_pid ());
在 psql 命令行中。
所以回到最初的问题:sdemurjian, 如果您想在某些触发功能中使用此通知,问题中没有说明。所以这里有一个例子(也许不是)给你(因为我来晚了。对此也很抱歉):
CREATE TABLE columns("columnID" oid, "columnData" text);
CREATE FUNCTION column_trigger_func() RETURNS TRIGGER AS
$$ BEGIN PERFORM pg_notify('columnchannel', 'Id: '||OLD."columnID");
RETURN NEW; END; $$ LANGUAGE plpgsql;
CREATE TRIGGER column_notify BEFORE UPDATE ON columns FOR EACH ROW
EXECUTE PROCEDURE column_trigger_func();
LISTEN columnchannel;
INSERT INTO columns VALUES(1,'testdata');
BEGIN; UPDATE columns SET "columnData" = 'success'; END;
BEGIN; UPDATE columns SET "columnData" = 'fail'; ROLLBACK;
请注意,在早期的 postgres 版本(9 之前的任何版本)中,notify 命令不接受任何负载并且没有 pg_notify 函数。
在 8.1 中,如果您像
那样定义触发器函数,它仍然可以工作CREATE FUNCTION column_trigger_func() RETURNS TRIGGER AS
$$ BEGIN NOTIFY columnchannel; RETURN NEW; END; $$ LANGUAGE plpgsql;