在PostgreSQL中使用pg_notify(text,text)进行LISTEN/NOTIFY

Abs*_*rct 16 database postgresql notifications

我一直在玩PostgreSQL的通知系统,并且在我的生活中无法解释为什么pg_notify(文本,文本)永远不会起作用.这个功能没有过多记录,我找不到很多在野外使用的例子,所以我想没有人会介意我在这里问.

运行以下工作完全符合预期:

LISTEN my_channel;

NOTIFY my_channel, 'my message text';
Run Code Online (Sandbox Code Playgroud)

但是,使用pg_notify()函数会返回一个空值,并且不会发送任何通知.也没有错误.一个例子是:

SELECT pg_notify('my_channel', 'my message text');
Run Code Online (Sandbox Code Playgroud)

我可以使用NOTIFY函数,但我的目标是将通知简化为如下查询:

select pg_notify(get_player_error_channel(username)::TEXT, 'test'::TEXT)
    from player;
Run Code Online (Sandbox Code Playgroud)

我认为我必须遗漏一些荒谬的东西,但我没有找到解决这个问题的原因.可以在此处找到讨论NOTIFY的页面:http://www.postgresql.org/docs/9.0/static/sql-notify.html

在它上面,它提到了关于pg_notify()的内容,这让我觉得没有什么大不相同的东西.

pg_notify 要发送通知,您还可以使用函数pg_notify(text,text).该函数将通道名称作为第一个参数,将有效负载作为第二个参数.如果您需要使用非常量通道名称和有效负载,则该功能比NOTIFY命令更容易使用.

一如既往地感谢您的帮助

编辑:数据库版本是:"i6486-pc-linux-gnu上的PostgreSQL 9.0.3,由GCC gcc(GCC)4.2.4编译,32位"

Abs*_*rct 26

我已经在PostgreSQL邮件列表(http://archives.postgresql.org/pgsql-bugs/2011-03/msg00041.php)上讨论了这个问题,并获知了该行为的原因.

他们的回答是"你必须加倍引用relnames(听"Test").如果你想让服务器不要将它们折叠起来.pg_notify需要一个字符串,而不是一个使用不同规则的relname." (谢谢Merlin和Tom)

这意味着以下工作原因是通道始终强制为小写

LISTEN ERRORCHANNEL;

NOTIFY ERRORCHANNEL, 'something!';
NOTIFY eRrorChanNel, 'something!';
Run Code Online (Sandbox Code Playgroud)

如果要在通道名称周围添加双引号,则会保留大小写.

因此,通过以下内容,您将收到第一个通知,但不会收到第二个通知:

LISTEN "ERRORCHANNEL";

NOTIFY "ERRORCHANNEL", 'something!'; 
NOTIFY "eRrorChanNel", 'something!';
Run Code Online (Sandbox Code Playgroud)

类似地,以下内容将起作用,因为双引号强制保持ERRORCHANNEL的大小写:

LISTEN "ERRORCHANNEL";

SELECT pg_notify('ERRORCHANNEL', 'something!');
Run Code Online (Sandbox Code Playgroud)

虽然这不起作用:

LISTEN ERRORCHANNEL;

SELECT pg_notify('ERRORCHANNEL', 'something!');
Run Code Online (Sandbox Code Playgroud)

在这种情况下,ERRORCHANNEL在LISTEN命令中不是双引号,因此PostgreSQL强制它为小写.channel参数的类型为text而不是relname,因此在pg_notify()函数中保持不变.通道一起不匹配(ERRORCHANNE!= errorchannel),因此永远不会收到通知.