2016-05-17 56 views
2

我有這樣的觸發器,以確保所有票數的總和沒有經過100:運行觸發交易之後,而不是在每行 - PostgreSQL的9.4

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的限制。

我希望它是有道理的。

我想觸發器被稱爲AFTER BEGIN ... COMMIT,所以我可以在檢查一切順序之前更新多行 - 但也會引發異常並且不保存結果,如果用戶嘗試更新票數超過100.

回答

7

觸發器必須是一個約束和「之後」觸發器。然後你可以使用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

+0

更改爲 「CREATE TRIGGER limit_votes BEFORE INSERT或更新汽車DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE limit_votes();」語法錯誤在「DEFERRABLE」處或附近失敗。 –

+0

@MichaelNielsen我已經更新了答案。 – freakish

+0

當它是一個AFTER觸發器時,如果某個「非法」被更新會發生什麼?它會被丟棄嗎? –

相關問題