更新特定列后的PostgreSQL触发器

zhte4eai  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(162)

我正在探索触发器,想创建一个在game_saved列上的Update事件后触发的触发器。正如我在PostgreSQL docs中所读到的,可以为列创建触发器。列包含boolean值,因此用户可以将游戏添加到他的收藏中或删除它。所以我希望触发器函数计算在game_saved列中设置为TRUE的游戏数量。game_saved列,然后更新game_collection表中的total_game_count

game_collection

id - BIGSERIAL primary key
user_id - INTEGER REFERENCES users(id)
total_game_count - INTEGER

字符串

game_info

id - BIGSERIAL primary key
user_id - INTEGER REFERENCES users(id)
game_id - INTEGER REFERENCES games(id)
review - TEXT
game_saved - BOOLEAN


这是我的触发器(它不起作用,我想找出原因):

CREATE OR REPLACE FUNCTION total_games() 
RETURNS TRIGGER AS $$ 
BEGIN 
UPDATE game_collection 
SET total_game_count = (SELECT COUNT(CASE WHEN game_saved THEN 1 END)
                        FROM game_info WHERE game_collection.user_id = game_info.user_id)
WHERE user_id = NEW.user_id; 
RETURN NEW; 
END; 
$$ LANGUAGE plpgsql; 

CREATE TRIGGER tr_total_games 
AFTER UPDATE OF game_saved FOR EACH ROW 
EXECUTE PROCEDURE total_games();


如果我将AFTER UPDATE OF game_saved(列)更改为AFTER UPDATE ON game_info(表),触发器就可以正常工作。
在列更新时触发触发器是个好主意,还是我应该在这里寻找另一种方法?

xxslljrj

xxslljrj1#

语法如下(如文档in the manual所示):

CREATE TRIGGER tr_total_games 
AFTER UPDATE OF game_saved ON game_info
FOR EACH ROW 
EXECUTE FUNCTION total_games();

字符串
对于Postgres 10或更早版本,用途:

...
EXECUTE PROCEDURE total_games();


参见:

但是整个方法是可疑的。在并发写负载下,使用触发器保持聚合最新很容易出错。如果没有并发写负载,有更简单的解决方案:只需从当前总数中加/减1...
VIEW是一个可靠的替代方案。完全删除列game_collection.total_game_count-也许是整个表game_collection,它似乎没有任何其他用途。创建一个VIEW

CREATE VIEW v_game_collection AS
SELECT user_id, count(*) AS total_game_count
FROM   game_info
WHERE  game_saved
GROUP  BY user_id;


这将返回在game_info(其中game_saved IS TRUE)中至少有一行的所有用户(并忽略所有其他用户)。
对于非常大的表,您可能需要MATERIALIZED VIEW或相关的解决方案来提高读取性能。这是性能、存储/缓存占用和最新性之间的权衡。

相关问题