当视图的内容间接更新时触发器不会触发

时间:2016-02-27 17:18:19

标签: postgresql view triggers

我开始对术语感到有些困惑,我开始相信我希望实现的目标是不可能的。是否可以创建一个触发器,当视图中的信息发生更改时触发,但不能通过视图本身上的UPDATE / INSERT / DELETE语句触发,而是在一个视图由哪些表组成?

如果没有,是否有一种有效的方法可以过滤哪些查询会触发一个触发器?

为了提供更多上下文,我有一个用户表和一个位置表。我只关心某个区域内每个用户的最新位置。我创建了一个视图如下:

CREATE OR REPLACE VIEW "users_near_coordinate" AS
SELECT DISTINCT ON ("User"."id") "User"."id", "User"."displayName", "UserLocation"."location", "UserLocation"."createdAt"
FROM "User", "UserLocation"
WHERE "UserLocation"."userId" = "User"."id" AND ST_Distance_Sphere(location, ST_MakePoint(long,lat)) <= 5 * 1609.34
ORDER BY "User"."id", "UserLocation"."createdAt" DESC;

然后我有一个触发器,如下所示:

CREATE OR REPLACE FUNCTION notify_user_moved_within_range() RETURNS trigger AS $$
DECLARE
BEGIN
  PERFORM pg_notify('user_nearby_inserted', TG_TABLE_NAME || ':' || NEW);
  RETURN new;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER "user_moved_within_range" INSTEAD OF INSERT ON "users_near_coordinate" FOR EACH ROW EXECUTE PROCEDURE notify_user_moved_within_range();

我也尝试过使用AFTER INSERT [...] FOR EACH STATEMENT的组合,但触发器似乎永远不会被触发。

要测试,我正在插入一个位置:

INSERT INTO "public"."UserLocation"("userId", "scenarioId", "location", "createdAt", "updatedAt") VALUES('8041849f-a204-4511-b6fa-74f3b731fd1f', '1', ST_GeomFromText('POINT(long lat)', 4326), now(), now());

1 个答案:

答案 0 :(得分:1)

视图只是SQL宏。它们实际上并不包含任何数据,当基础表更新时,视图中的任何内容都不会发生变化。因此,视图上没有可能触发触发器的INSERT事件;你需要把扳机放在桌子上。

通过将WHEN (<condition>) clause附加到CREATE TRIGGER语句,您可以轻松定义有条件触发的触发器。或者,您可以将条件逻辑放在触发器函数中,即:

IF <condition> THEN
  PERFORM pg_notify(...);
END IF;
相关问题