Eu tenho esta tabela:
CREATE TABLE accounts (
id BIGINT NOT NULL UNIQUE,
balance INTEGER DEFAULT 0
);
E preciso atualizar o saldo de cada usuário após inserir linhas em 2 tabelas diferentes transfers
e deposits
.
Criei 2 funções para calcular novos saldos de usuários e atualizá-los:
/* 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;
Mas não tenho certeza de como usar os valores recém-inseridos em um retorno de chamada de gatilho, porque preciso passar o id
como um argumento para a upsert_balance
função.
Como posso fazer isso?
EDIT: Eu consertei, graças à resposta de Adam, aqui está a versão de trabalho, caso alguém precise:
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();
Dentro da função de gatilho, você pode usar NEW.column_name para se referir ao valor recém-inserido/atualizado. No reverso, OLD.column_name fará referência ao valor anterior à atualização/exclusão.
Mais informações aqui: https://www.postgresql.org/docs/current/static/sql-createtrigger.html
Espero que ajude.
Dentro da função de disparo, você pode usar
NEW.column_name
para se referir ao valor recém-inserido ou atualizado. No reverso,OLD.column_name
fará referência ao valor anterior à atualização ou exclusão.Mais informações aqui: https://www.postgresql.org/docs/current/static/sql-createtrigger.html
Espero que ajude.