sam*_*mba 1 sql postgresql triggers database-design
我正在探索触发器,并且希望创建一个在game_saved列上的Update事件后触发的触发器。正如我在PostgreSQL文档中所读的那样,可以为列创建触发器。该列包含boolean值,因此用户可以将游戏添加到他的收藏中或将其删除。因此,我希望触发函数能够game_saved为特定用户计算列中设置为TRUE的游戏数量。然后total_game_count在一个game_collection表中更新。
game_collection
id - BIGSERIAL primary key
user_id - INTEGER REFERENCES users(id)
total_game_count - INTEGER
Run Code Online (Sandbox Code Playgroud)
game_info
id - BIGSERIAL primary key
user_id - INTEGER REFERENCES users(id)
game_id - INTEGER REFERENCES games(id)
review - TEXT
game_saved - BOOLEAN
Run Code Online (Sandbox Code Playgroud)
这是我的触发器(它不起作用,我想找出原因):
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();
Run Code Online (Sandbox Code Playgroud)
如果我将AFTER UPDATE OF game_saved(列)更改为AFTER UPDATE ON game_info(表),则触发器可以正常工作。因此,创建专门用于列更新的触发器存在一些问题。
在列更新上触发触发器是一个好主意,还是我应该在这里寻找另一种方法?
语法为:
CREATE TRIGGER tr_total_games
AFTER UPDATE OF game_saved ON game_info
FOR EACH ROW
EXECUTE PROCEDURE total_games();Run Code Online (Sandbox Code Playgroud)
但是整个方法是可疑的。在并发写入负载下,通过触发器使聚合保持最新状态容易出错。
没有并发写入负载,有更简单的解决方案:只需从当前总数中加/减1 ...
可靠的解决方案是VIEW。game_collection.total_game_count完全删除该列,也可能删除整个表game_collection,这似乎没有其他用途。
CREATE VIEW v_game_collection AS
SELECT user_id, count(*) AS total_game_count
FROM game_info
WHERE game_saved
GROUP BY user_id;
Run Code Online (Sandbox Code Playgroud)
这将返回在game_info其中至少有1行的所有用户game_saved IS TRUE(并忽略所有其他用户)。
对于非常大的表,您可能需要MATERIALIZED VIEW或相关的解决方案来提高读取性能。
| 归档时间: |
|
| 查看次数: |
2596 次 |
| 最近记录: |