database - 在 PostgreSQL 触发器函数中使用 pg_notify

标签 database postgresql triggers notifications plpgsql

我正在尝试从 PostgreSQL 触发器函数发出通知。我可以成功地使用 NOTIFY 命令,但我对 pg_notify 没有任何运气。尽管我在从 psql 控制台调用 pg_notify 函数时收到通知,但在从我的触发器函数调用相同函数时我从未收到通知。

我的触发函数的这个版本按预期工作。我有一个 Java 程序正在监听“mymessage”,它收到一个带有“由 NOTIFY 触发”负载的通知。

-- Function: conversation_notify()

-- DROP FUNCTION conversation_notify();

CREATE OR REPLACE FUNCTION conversation_notify()
  RETURNS trigger AS
$BODY$
    BEGIN
        --SELECT pg_notify('mymessage', 'fired by FUNCTION');
        NOTIFY mymessage, 'fired by NOTIFY';
        RETURN NULL;
    END; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION conversation_notify() OWNER TO postgres;

我的触发函数的这个版本没有按预期工作。唯一的变化是取消注释 pg_notify 行并注释掉下面的 NOTIFY 行。 (我没有修改 LISTENing 的 Java 应用程序。)我希望我的应用程序 LISTENing to 'mymessage' 应该收到一个带有 'fired by FUNCTION' 负载的通知。实际行为是什么也没有收到,即使在相应表被修改后 30 秒以上也是如此。

-- Function: conversation_notify()

-- DROP FUNCTION conversation_notify();

CREATE OR REPLACE FUNCTION conversation_notify()
  RETURNS trigger AS
$BODY$
    BEGIN
        SELECT pg_notify('mymessage', 'fired by FUNCTION');
        --NOTIFY mymessage, 'fired by NOTIFY';
        RETURN NULL;
    END; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION conversation_notify() OWNER TO postgres;

但是,我真的感到困惑,因为相同的 pg_notify 命令在 psql 控制台中按预期工作!当我执行以下命令时,我的 Java 应用程序收到一个带有“由 CONSOLE 触发”负载的通知:

select pg_notify('mymessage', 'fired by CONSOLE');

为了完整性,这里是我的触发器定义:

-- Trigger: conversation_notify on ofconversation

-- DROP TRIGGER conversation_notify ON ofconversation;

CREATE TRIGGER conversation_notify
  AFTER INSERT OR UPDATE
  ON ofconversation
  FOR EACH ROW
  EXECUTE PROCEDURE conversation_notify();

我正在尝试使用 pg_notify,因为我想要一个动态负载。现在,这是一个有争议的问题。 :) Postgres 9.0 手册表明这应该是可能的。 The NOTIFY docs对于“有效负载”参数状态:

(If binary data or large amounts of information need to be communicated, it's best to put it in a database table and send the key of the record.)

我还引用了一个相关的 Stack Overflow 问题,我想我已经避开了这个问题:LISTEN/NOTIFY using pg_notify(text, text) in PostgreSQL .

数据库版本为:

PostgreSQL 9.0.3, compiled by Visual C++ build 1500, 32-bit

我的操作系统是 Windows XP Professional,版本 2002,SP3。

提前致谢。

编辑:在下面添加了我的 Java 监听器代码。它基于 PostgreSQL 文档中的示例: http://jdbc.postgresql.org/documentation/81/listennotify.html .

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.postgresql.PGConnection;
import org.postgresql.PGNotification;

public class ConversationListener extends Thread
{   
    private Connection conn;
    private PGConnection pgConn;

    public ConversationListener(Connection conn) throws SQLException
    {
        this.conn = conn;
        this.pgConn = (PGConnection) conn;
        Statement listenStatement = conn.createStatement();
        listenStatement.execute("LISTEN mymessage");
        listenStatement.close();
    }

    @Override
    public void run()
    {
        while (true)
        {
            try
            {
                // issue a dummy query to contact the backend
                // and receive any pending notifications.
                Statement selectStatement = conn.createStatement();
                ResultSet rs = selectStatement.executeQuery("SELECT 1");
                rs.close();
                selectStatement.close();

                PGNotification notifications[] = pgConn.getNotifications();

                if (notifications != null)
                {
                    for (PGNotification pgNotification : notifications)
                    {
                        System.out.println("Got notification: " + pgNotification.getName() +
                            " with payload: " + pgNotification.getParameter());
                    }
                }

                // wait a while before checking again
                Thread.sleep(500);
            }
            catch (SQLException sqlException)
            {
                sqlException.printStackTrace();
            }
            catch (InterruptedException ie)
            {
                ie.printStackTrace();
            }
        }
    }
}

这是一个简单的 Java 1.6 SE 桌面应用程序,因此我正在管理我自己的 JDBC 连接和所有内容。我正在通过

加载驱动程序
Class.forName("org.postgresql.Driver");

我正在使用 postgresql-9.0-801.jdbc3.jar 库(我的类路径中只有一个)和 JDK 1.6.0_22。

回顾一下上面的内容,Java 代码可以很好地处理来自 psql 的 NOTIFY 和触发器,以及来自 psql 的 pg_notify。

最佳答案

这可能来不及提供帮助,但也许其他人能够使用它。 使用 SELECT pg_notify('', '');在触发器中导致数据库响应

ERROR: query has no destination for result data
SQL state: 42601
Hint: If you want to discard the results of a SELECT, use PERFORM instead.

按照错误提示将 SELECT 更改为 PERFORM 有助于解决此问题,并且通知会按预期发送。也许这可能是问题所在。

我有同样的设置,也遇到了同样的问题。

关于database - 在 PostgreSQL 触发器函数中使用 pg_notify,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5412474/

相关文章:

mysql - 如何汇总 MySQL 表中的连续行

node.js - 查询失败错误 : the column "price" contain null values - TypeORM - PostgreSQL

postgresql - 带触发器的 Postgres 分区管理。发行变更表

MySQL:DROP PARTITION 是否触发了 TRIGGER ON DELETE?

mySQL MATCH AGAINST 包含的字符串

php - 编辑前置任务时调整数据库中的后续任务日期

database - 一对多数据库关系

php - bitvalue 为 false 时出现 PostgreSQL 错误

sql - 为什么 postgresql 不使用我的 group by 聚合索引?

java - 如何检查哪个 Quartz Scheduler 作业没有运行