简体   繁体   English

我如何发送列值作为Postgresql NOTIFY消息中的有效载荷?

[英]How can I send column values as the payload in a postgresql NOTIFY message?

If an entry in a table satisfies certain conditions, a NOTIFY is sent out. 如果表中的条目满足某些条件,则发出NOTIFY。 I want the payload to include the ID number and several other columns of information. 我希望有效负载包括ID号和其他几列信息。 Is there a postgres method to convert variables (OLD.ColumnID, etc) to strings? 是否有一种postgres方法将变量(OLD.ColumnID等)转换为字符串?

using postgres 9.3 使用Postgres 9.3

@klin is correct that NOTIFY doesn't support anything other than string literals. @klin是正确的,即NOTIFY除字符串文字外不支持任何其他内容。 However there is a function pg_notify() which takes normal arguments to deal with exactly this situation. 但是,有一个函数pg_notify()接受普通参数来处理这种情况。 It's been around since at least 9.0 and that link is to the official documentation - always worth reading it carefully, there is a wealth of information there. 至少从9.0开始就存在,并且该链接指向官方文档-始终值得仔细阅读,那里有大量信息。

My guess is that the notify has to be done within a trigger function. 我的猜测是,通知必须在触发函数中完成。 Use a dynamic query, eg 使用动态查询,例如

execute format('notify channel, ''id: %s''', old.id);

解决方案是将Postgres升级到支持JSON的版本。

Even postgresql 9.3 supports json. 甚至Postgresql 9.3也支持json。 You could have just used row_to_json(payload)::text 您可能刚刚使用过row_to_json(payload)::text

Sorry for the long answer, i just cant walk away without reacting to the other answers too. 很抱歉,答案很长,我也不能不对其他答案做出反应而走开。

The format version fails in many ways. format版本在许多方面失败。 Before EXECUTE, you shoud prepare the plan. 在执行之前,您应该准备计划。 The "pseudo command" does not fits the syntax of execute which is “伪命令”不符合execute的语法,即

EXECUTE somepreparedplanname (parameter1, ...)

The %s in format is again too bad, this way you can summon sql injection attacks. 格式中的%s太糟糕了,这样您可以召唤sql注入攻击。 When constructing a query with format , you need to use %L for literals %I for column/table/function/etc ids, and use %s almost never. 当使用format构造查询时,您需要将%L用作文字%I来用作column / table / function / etc id,而几乎不使用%s。

The other solution with the pg_notify function is correct. 使用pg_notify函数的另一个解决方案是正确的。 Try 尝试

LISTEN channel;
SELECT pg_notify('channel','Id: '|| pg_backend_pid  ());

in psql command line. 在psql命令行中。

So back to the original question: sdemurjian, Its not clarified in the question, if you wants to use this notification thing in some trigger function. 回到最初的问题:sdemurjian,如果您想在某些触发函数中使用此通知内容,则在问题中未阐明。 So here is an example (maybe not) for you (because im a little late. sorry for that too): 因此,这里有一个示例(可能不是)(因为我来晚了。对此也感到抱歉):

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;

Please note that in early postgres versions (any before 9), the notify command does not accepts any payload and there is no pg_notify function. 请注意,在早期的postgres版本(9之前的版本)中,notify命令不接受任何有效载荷,并且没有pg_notify函数。

In 8.1 the trigger function stil works if you define it like 在8.1中,触发函数stil的工作方式如下:

CREATE FUNCTION column_trigger_func() RETURNS TRIGGER AS
$$ BEGIN NOTIFY columnchannel; RETURN NEW; END; $$ LANGUAGE plpgsql;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM