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
.
来避免这种情况
所以,我有一个 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
后考虑 tableid |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
.