I want to create a trigger on a game_catalog table so that every time a user adds or deletes a game from his collection the total game count gets updated. Since the game collection is stored as a text array I decided to use array_length function to count the number of games.
game_catalog
id - BIGSERIAL primary key
user_id - INTEGER
game_list - text []
game_count - INTEGER
I've attempted to create a trigger so that it recalculates the length of the game_list column after insert or delete but it does not work. Here is what I have for now:
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();
So, a couple of things:
That said, you can define your trigger differently to make it work:
-- 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();
Although a view would be better:
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;
And your trigger function could use a little improvement (unless you do plan to reference other rows... but then you have other problems in your trigger function design):
CREATE OR REPLACE FUNCTION count_games()
RETURNS TRIGGER AS $$
BEGIN
NEW.game_count := array_length(NEW.game_list, 1);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Hope that is helpful!