我正在探索触发器,想创建一个在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
(表),触发器就可以正常工作。
在列更新时触发触发器是个好主意,还是我应该在这里寻找另一种方法?
1条答案
按热度按时间xxslljrj1#
语法如下(如文档in the manual所示):
字符串
对于Postgres 10或更早版本,用途:
型
参见:
但是整个方法是可疑的。在并发写负载下,使用触发器保持聚合最新很容易出错。如果没有并发写负载,有更简单的解决方案:只需从当前总数中加/减1...
VIEW
是一个可靠的替代方案。完全删除列game_collection.total_game_count
-也许是整个表game_collection
,它似乎没有任何其他用途。创建一个VIEW
:型
这将返回在
game_info
(其中game_saved IS TRUE
)中至少有一行的所有用户(并忽略所有其他用户)。对于非常大的表,您可能需要
MATERIALIZED VIEW
或相关的解决方案来提高读取性能。这是性能、存储/缓存占用和最新性之间的权衡。