我有这个触发器来确保所有投票的总和不会超过100:
CREATE FUNCTION limit_votes() RETURNS TRIGGER AS $limit_votes$
DECLARE
votes_total int;
BEGIN
votes_total := NEW.vote + (SELECT SUM(vote) FROM cars WHERE portfolio_id = NEW.portfolio_id AND car != NEW.car);
IF votes_total > 100 THEN
RAISE EXCEPTION 'votes_limit_exceeded';
END IF;
RETURN NEW;
END;
$limit_votes$ LANGUAGE plpgsql;
CREATE TRIGGER limit_votes BEFORE INSERT OR UPDATE ON cars FOR EACH ROW EXECUTE PROCEDURE limit_votes();
应该提到的是"投票"可以更新,所以它不仅是INSERT。 这就是我的问题发生的地方,因为一个用户可以更改汽车之间的投票,然后触发器被发出,因为单个行的更新可能超过100的限制,然后其他更新减少其他投票。
我希望它有意义。
我希望在BEGIN ... COMMIT之后调用触发器,所以我可以在检查所有内容之前更新多行 - 但是如果用户尝试更新投票,也会引发异常而不保存结果超过100。
答案 0 :(得分:9)
触发器必须是约束和“后”触发器。然后你可以使用DEFERRABLE:
CREATE CONSTRAINT TRIGGER limit_votes
AFTER INSERT OR UPDATE ON cars
DEFERRABLE
FOR EACH ROW EXECUTE PROCEDURE limit_votes();
参见文档:
http://www.postgresql.org/docs/9.1/static/sql-createtrigger.html
答案 1 :(得分:0)
根据https://www.postgresql.org/docs/13/sql-createtrigger.html
由于这应该是一个延迟约束,并且您希望在事务之后触发过程执行,因此您需要以下内容,
CREATE CONSTRAINT TRIGGER limit_votes
AFTER INSERT OR UPDATE ON cars
DEFERRABLE
INITIALLY DEFERRED
FOR EACH ROW EXECUTE PROCEDURE limit_votes();
如果我们想在每个语句之后触发过程执行。
CREATE CONSTRAINT TRIGGER limit_votes
AFTER INSERT OR UPDATE ON cars
DEFERRABLE
INITIALLY IMMEDIATE
FOR EACH ROW EXECUTE PROCEDURE limit_votes();