在触发器内部调用的postgres函数中的select语句

时间:2019-04-11 04:17:43

标签: postgresql plpgsql database-trigger

我正在尝试为社交媒体应用程序/网站的后端开发一个通知系统。现在,我专注于状态更新。我要做的是在与状态更新相关的postgres表上放置一个触发器,以便每次发布新的状态更新时,都会向我的代码发送一条通知。

到目前为止,我已经能够做到这一点。但是我想实现的一项附加功能是提取所有关注发布状态更新用户的人员,以便我还可以向他们发送通知,通知他们关注的人员发布了新状态更新。

当然可以通过首先从postgres接收有关新状态更新的通知,提取发布者的用户ID,然后查询数据库以找出哪些用户关注它们,来实现该实现。

但是我认为如果不进行查询,效率会更高,相反,每次postgres想要向我发送有关新状态更新的通知时,它也会进行查询以找出正在关注的用户状态更新的发布者,并将该信息与新状态更新的通知一起发送。

但是我无法弄清楚如何在依赖该函数参数的postgres函数中进行查询,然后将该查询的结果与该参数一起作为通知发送。

这是我尝试过的:

create table example (c1 text, c2 text);

create function notif() 
   returns trigger as 
$$ 
begin 
  perform pg_notify('event',row_to_json(new)::text); 
  return new; 
end; 
$$ language plpgsql;

create trigger trig after insert 
   on example 
   for each row execute procedure notif();

然后,我从代码中侦听事件通道,并接收插入的行。但是我想在我的notif()函数中基于新行执行一条select语句,并将新行的结果发送到侦听代码。

请您澄清一下

谢谢

1 个答案:

答案 0 :(得分:0)

像这样吗?

CREATE FUNCTION notif()
RETURNS TRIGGER AS $$
DECLARE
    data JSONB;
    result JSONB;
BEGIN
    SELECT json_agg(tmp)  -- requires Postgres9.3+
    INTO data
    FROM (
        -- your subquery goes here, for example:
        SELECT followers.following_user_id
        FROM followers
        WHERE followers.followed_user_id = NEW.user_id
    ) tmp;

    result := json_build_object('data', data, 'row', row_to_json(NEW));
    PERFORM pg_notify('event', result::TEXT);
    RETURN NEW;
END;
$$ language plpgsql;

也来自评论:

  

但是以某种神奇的方式使用return new将该行返回到通知中。

您误会了事情。 返回和通知是两回事。

首先让我们处理退货。对于AFTER INSERT触发器,返回值将被完全忽略

  

总是会忽略行级触发器AFTER触发后或语句级触发器BEFORE或AFTER触发的返回值;它也可能为空。

返回值仅对BEFORE触发器有效。在这种情况下,您可以在写入表之前修改(甚至阻止)该行。看到以下内容:https://www.postgresql.org/docs/9.2/plpgsql-trigger.html 与通知无关。

那通知呢? 从通知中收到的所有内容都是您作为第二个参数传递给pg_notify的信息。所有这些都得到了充分的记录:https://www.postgresql.org/docs/9.0/sql-notify.html