我正在探索触发器的方式,并希望创建一个在boolean
列上的Update事件后触发的触发器。正如我在PostgreSQL docs中读到的那样,可以为列创建触发器。该列包含game_saved
值,因此用户可以将游戏添加到其集合中或将其删除。所以我希望触发器功能计算某个用户在total_game_count
列中设置为TRUE的游戏数量。然后在game_collection
表中更新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}}(表格),则触发器可以正常工作。因此,专门为列更新创建触发器存在一些问题。
在列更新时触发触发器是一个好主意还是我应该在这里寻找其他方法?
答案 0 :(得分:4)
语法为:
CREATE TRIGGER tr_total_games
AFTER UPDATE OF game_saved ON game_info
FOR EACH ROW
EXECUTE PROCEDURE total_games();
(As documented in the manual.)
但整个方法都是可疑的。通过触发器保持聚合更新在并发写入负载下容易出错。
没有并发写入加载,有更简单的解决方案:只需从当前总计中加/减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;
这将返回game_info
中game_saved IS TRUE
至少有1行的所有用户(并忽略所有其他行)。
对于非常大的表,您可能需要MATERIALIZED VIEW
或相关解决方案来提高读取性能。