postgres:函数 select 并通知

postgres: function with select and notify

所以,我有一个 table 描述了一些实体在 space 中的位置(为了简单起见,在一个维度上,原始问题是相关的)

    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;

如何改成只有在同一个位置的实体很少时才通知的功能

例如update

后考虑 table
id  |positions
-------------
id1 |10
id2 |10
id3 |11

我需要用字符串调用通知'id1,id2'

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

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

  • 如果当前没有实体位于新位置,则什么也不做。
  • 否则调用 notify 并使用 comma-separated 当前位于新位置的实体 ID 列表。

您可以在触发器函数中实现此目的,方法是使用 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.

来避免这种情况