2016-02-27 89 views
1

我开始对术语有点困惑,我开始相信我所希望实现的是不可能的。是否有可能创建一个触发器,当视图内的信息发生变化时触发,而不是通过视图本身的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

次数比SQL宏的更多一点。它们实际上并不包含任何数据,并且在更新基础表时,视图中的任何内容都不会改变。因此,视图上没有INSERT事件可能触发触发器;你需要把你的触发器放在桌子上。

通过将WHEN (<condition>) clause附加到CREATE TRIGGER语句中,您可以轻松定义触发条件触发条件。或者,您可以将条件逻辑置于触发器功能本身,即:

IF <condition> THEN 
    PERFORM pg_notify(...); 
END IF; 
+0

这似乎是我正在寻找的解决方案。一旦我有一个粗糙的版本工作,我会给它一个镜头并标记为正确的。你可以建议将条件添加到CREATE TRIGGER语句与函数内吗?理论上,我的解决方案应该能够扩展到非常多的触发器 –