J'ai cette table:
CREATE TABLE accounts (
id BIGINT NOT NULL UNIQUE,
balance INTEGER DEFAULT 0
);
Et je dois mettre à jour la balance de chaque utilisateur après avoir inséré des lignes sur 2 tables différentes, transfers
et deposits
.
J'ai créé 2 fonctions pour calculer de nouveaux soldes utilisateur et la mise à jour:
/* function for getting user balance */
CREATE FUNCTION get_balance(bigint) RETURNS bigint
AS 'SELECT (
SELECT COALESCE(sum(CASE WHEN won THEN amount * (multiplier - 1) ELSE -amount END), 0)
FROM transfers
WHERE user_id = $1
) + (
SELECT COALESCE(sum(amount), 0)
FROM deposits
WHERE user_id = $1
) as sum;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
/* function for updating user balance */
CREATE FUNCTION upsert_balance(bigint) RETURNS VOID
AS 'INSERT INTO ACCOUNTS (id, balance)
VALUES ($1, get_balance($1))
ON CONFLICT (id) DO
UPDATE SET balance = get_balance($1);'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
Mais je ne sais pas comment utiliser les valeurs nouvellement insérées dans un raccord de déclenchement, car je dois passer le id
comme argument sur le upsert_balance
une fonction.
Comment puis-je accomplir cela?
Edit: Je l'ai réparé, grâce à la réponse d'Adam, voici la version de travail au cas où quelqu'un en a besoin:
CREATE FUNCTION upsert_balance() RETURNS trigger AS $trigger_bound$
BEGIN
INSERT INTO ACCOUNTS (id, balance)
VALUES (NEW.user_id, get_balance(NEW.user_id))
ON CONFLICT (id) DO
UPDATE SET balance = get_balance(NEW.user_id);
RETURN NEW;
END;
$trigger_bound$
LANGUAGE plpgsql;
CREATE TRIGGER update_balance_on_inserting_transfer
AFTER INSERT OR UPDATE ON transfers
FOR EACH ROW
EXECUTE PROCEDURE upsert_balance();
Dans la fonction de déclenchement, vous pouvez utiliser New.Column_Name pour faire référence à la valeur nouvellement insérée/mise à jour. Dans l'inverse, Old.Column_Name se référera à la valeur avant la mise à jour/supprimer.
Plus d'infos Ici: https://www.postgresql.org/docs/current/static/sql-createtrigger.html
J'espère que cela pourra aider.