2017-04-22 39 views
0

我想在game_catalog表上創建觸發器讓每一位用戶添加或刪除從他的收藏遊戲的總遊戲數被更新的時間。由於遊戲集合存儲爲文本數組,我決定使用array_length函數來計算遊戲數量。PostgreSQL觸發對INSERT,UPDATE,遊戲數/數組元素的刪除

game_catalog

id - BIGSERIAL primary key 
user_id - INTEGER 
game_list - text [] 
game_count - INTEGER 

我試圖使其重新計算game_list柱插入後的長度創建觸發器或刪除,但它不工作。以下是我對現在:

CREATE OR REPLACE FUNCTION count_games() 
RETURNS TRIGGER AS $$ 
BEGIN 
UPDATE game_catalog 
SET game_count = (SELECT array_length(game_list, 1) from game_catalog) 
WHERE user_id = NEW.user_id; 
RETURN NEW; 
END; 
$$ LANGUAGE plpgsql; 

CREATE TRIGGER count_games 
AFTER INSERT OR DELETE ON game_catalog FOR EACH ROW 
EXECUTE PROCEDURE count_games(); 
+0

很奇怪。如果遊戲列表在數組中,則不會發生插入或刪除操作 - 僅更新 - 爲用戶更新行,更改'game_list'字段... –

回答

1

所以,幾件事情:

  • 我不知道您的具體使用情況,但是這似乎是有幾個原因是一個壞主意
  • 請確保你有你的user_id唯一約束或這將變得混亂(你鑰匙上的user_id爲您更新,更好的使用主鍵,如果你打算在什麼鍵,但它是不是真的有必要,如圖所示)[編輯 - 沒關係。你的查詢處理了這個。但是,你更新該用戶的每一條記錄......這能得到昂貴的,如果有重複...]
  • 如果你真的想這個項目是提供給用戶,而不計算它(因爲它總是引用相同行),它看起來對我來說,它確實屬於視圖或物化視圖
  • 通常情況下,觸發聚合是表級聚合時,預計大量數據(即不被記錄),並且將生活在一個單獨的表。當它在同一個表,你運行一個無限循環的風險(更新一排,觸發更新,觸發更新等)
  • 一般情況下,你應該問自己很多問題使用數組或之前json列關係數據建模。雖然有可能,你可以爲你的未來的自己
  • 對於DELETE觸發器創建疼痛,NEW是不確定的(見Postgres的文檔上的觸發功能,他們是非常有益的,有一些很好的例子)
  • 如果編輯記錄本身隨着它進入(更高效,因爲你沒有選擇查詢),你需要使用BEFORE觸發器,因爲AFTER觸發器不能改變進入表的事物的值。

這就是說,你可以定義不同的觸發,使其工作:

-- only watch for insert/updates on the game_list column to avoid infinite loop 
-- delete doesn't matter here 
CREATE TRIGGER count_games 
BEFORE INSERT OR UPDATE OF game_list 
ON game_catalog 
FOR EACH ROW 
EXECUTE PROCEDURE count_games(); 

雖然景色會更好:

CREATE OR REPLACE VIEW game_catalog_count AS 
SELECT id, user_id, game_list, array_length(game_list,1) as game_count 
FROM game_catalog; 

而且你的觸發功能可以使用一個小的改進(除非你打算參考其他行......但你必須在你的觸發功能設計等問題):

CREATE OR REPLACE FUNCTION count_games() 
RETURNS TRIGGER AS $$ 
BEGIN 

NEW.game_count := array_length(NEW.game_list, 1); 

RETURN NEW; 
END; 
$$ LANGUAGE plpgsql; 

希望有幫助!