postgres:具有select和notify

时间:2018-02-15 17:05:13

标签: sql postgresql triggers publish-subscribe

所以,我有一个表格,描述了一些实体在太空中的位置(为了简单起见,原始问题是相关的)

    CREATE TABLE positions(
       id VARCHAR (32) UNIQUE NOT NULL,
       position VARCHAR (50) NOT NULL
    );

我创建了一个触发器,通知每次更新

  CREATE TRIGGER position_trigger AFTER UPDATE ON positions
  FOR EACH ROW
  EXECUTE PROCEDURE notify_position();

和一个功能:

CREATE FUNCTION notify_position() RETURNS trigger AS $$
DECLARE
  BEGIN
    PERFORM pg_notify(
      'positions',
      TG_TABLE_NAME || ',id,' || NEW.id || ',position,' || NEW.position
    );
    RETURN new;
END;
$$ LANGUAGE plpgsql;

如何将功能更改为仅在同一位置的实体很少时才通知。

e.g。更新后考虑一个表

id  |positions
-------------
id1 |10
id2 |10
id3 |11

我需要使用字符串'id1,id2'

调用notify

可能,我需要以某种方式选择与更新的一个具有相同位置的所有实体并创建它们的列表(包含逗号分隔的ID的字符串)。我怎么能这样做?

1 个答案:

答案 0 :(得分:1)

根据我对您的问题的理解,您希望在实体的职位更新时发生以下情况:

  • 如果当前没有实体处于新职位,则不执行任何操作。
  • 否则,请使用以逗号分隔的当前处于新位置的实体ID列表来调用notify。

您可以在触发器功能中使用string_agg聚合函数来构建匹配实体的ID列表,然后在调用pg_notify之前检查其长度:

CREATE FUNCTION notify_position() RETURNS trigger AS $$
DECLARE
  colocated_ids TEXT;
BEGIN
  -- Construct list of IDs of co-located entities.
  colocated_ids := (
    SELECT string_agg(id, ',')
    FROM positions
    WHERE position = NEW.position AND id != NEW.id
  );

  -- Notify listeners if some co-located entities were found.
  IF length(colocated_ids) > 0 THEN
    PERFORM pg_notify('positions', colocated_ids);
  END IF;

  RETURN new;
END;
$$ LANGUAGE plpgsql;

请注意,如果没有AND id != NEW.id检查,更新实体的ID也会显示在列表中。你可以通过触发BEFORE UPDATE而不是AFTER UPDATE来避免这种情况。