簡體   English   中英

PostgreSQL觸發器可在插入/刪除數組元素時更新游戲計數

[英]PostgreSQL Trigger to update game count on insert/delete of array elements

我想在game_catalog表上創建一個觸發器,以便每次用戶從其收藏game_catalog中添加或刪除游戲時,總游戲計數都會更新。 由於游戲集合存儲為文本數組,因此我決定使用array_length函數來計算游戲數量。

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(); 

因此,有兩件事:

  • 我不知道您的確切用例,但是出於某些原因,這似乎是個壞主意
  • 請確保您對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; 

希望對您有所幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM