PostgreSQL触发器和通知函数未按预期工作

x7yiwoj4  于 2023-10-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(137)

问题:

我已经设置了一个PostgreSQL函数和触发器,当RiderDataPosition表上有INSERTUPDATEDELETE操作时发送通知。然而,尽管我努力了,我还是没有收到任何预期的通知。我正在寻求解决此问题的指导。我的最终结果是,当RiderDataPosition表中的某些内容发生更改时,我希望得到通知。

更新

当向数据库发送查询NOTIFY RiderPositionUpdate时,我的测试应用程序收到响应。这意味着触发器出了问题

问题描述:

我在Docker容器中运行了一个PostgreSQL数据库,我使用的是最新版本。目标是每当RiderDataPosition表中发生更改时向RiderPositionUpdate通道发送通知。以下是我到目前为止所做的:
1.通知功能:
我创建了一个通知函数如下:

CREATE OR REPLACE FUNCTION "TrackSolutionsCore".notify_rider_position_change()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' THEN
        PERFORM pg_notify('RiderPositionUpdate', json_build_object('operation', 'insert', 'record_id', NEW."TransponderId")::text);
        RAISE NOTICE 'Inserted record with TransponderId %', NEW."TransponderId";
        RETURN NEW;
    ELSIF TG_OP = 'UPDATE' THEN
        PERFORM pg_notify('RiderPositionUpdate', json_build_object('operation', 'update', 'record_id', NEW."TransponderId")::text);
        RAISE NOTICE 'Updated record with TransponderId %', NEW."TransponderId";
        RETURN NEW;
    ELSIF TG_OP = 'DELETE' THEN
        PERFORM pg_notify('RiderPositionUpdate', json_build_object('operation', 'delete', 'record_id', OLD."TransponderId")::text);
        RAISE NOTICE 'Deleted record with TransponderId %', OLD."TransponderId";
        RETURN OLD;
    END IF;
END;
$$ LANGUAGE plpgsql;

1.触发器:
我已经为RiderDataPosition表上的AFTER INSERTAFTER UPDATEAFTER DELETE操作创建了触发器。下面是其中一个触发器的例子:

CREATE TRIGGER rider_data_position_insert_trigger
AFTER INSERT ON "TrackSolutionsCore"."RiderDataPosition"
FOR EACH ROW
EXECUTE FUNCTION "TrackSolutionsCore".notify_rider_position_change();

1.表格结构:
RiderDataPosition表具有以下结构:

CREATE TABLE "RiderDataPosition"
(
    "TransponderId" integer generated by default as identity
        constraint "PK_RiderDataPosition"
            primary key,
    -- Other columns...
);

面临的问题:

尽管设置了这些触发器和通知功能,但当我对RiderDataPosition表执行CRUD操作时,我在RiderPositionUpdate通道上没有收到任何通知。我尝试过使用NotificationEventHandler通过C#应用程序接收这些通知,也尝试过通过在控制台中执行LISTEN "RiderPositionUpdate"直接通过DataGrip接收这些通知,但这两种方法都没有结果。

环境:

  • PostgreSQL版本:[16个]
  • Docker引擎:[v24.0.6]
    测试申请
using Npgsql;

var conn = new NpgsqlConnection("connectionString");
conn.Open();
conn.Notification += (o, e) => Console.WriteLine("Received notification");

using (var cmd = new NpgsqlCommand("LISTEN RiderPositionUpdate", conn)) {
    cmd.ExecuteNonQuery();
}

while (true) {
    conn.Wait();   // Thread will block here
}

在DataGrip中插入新记录后的输出

问题:

1.是什么原因导致了这个问题,我如何进一步解决这个问题?
1.是否有任何特定的PostgreSQL配置或Docker设置我应该检查,以确保通知工作正常?
1.有没有一种方法可以验证触发器和函数是否正在发送通知,可能是通过PostgreSQL日志或其他方法?
1.在设置PostgreSQL触发器和通知函数时,是否有我可能忽略的常见陷阱或错误?
任何关于如何诊断和解决这个问题的见解或指导将不胜感激。谢谢你,谢谢!

k10s72fa

k10s72fa1#

你的病例不匹配。如果通道名称包含真实的大写字母,则在LISTEN命令中必须将该名称用双引号括起来。您的NOTIFY命令与您的LISTEN一起工作,因为它与LISTEN一样大小写折叠通道名称,而pg_notify没有大小写字段其第一个参数,因此它不起作用。
但更好的是,改变你的频道名称,使它没有大写字母。

相关问题