web-dev-qa-db-ja.com

PostgreSQLのトリガー関数で新しく挿入された値を使用する

私はこのテーブルを持っています:

CREATE TABLE accounts (
  id BIGINT NOT NULL UNIQUE,
  balance INTEGER DEFAULT 0
);

そして、2つの異なるテーブルtransfersdepositsに行を挿入した後、各ユーザーの残高を更新する必要があります。

新しいユーザーの残高を計算して更新する2つの関数を作成しました。

/* 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;

しかし、idupsert_balance関数の引数として渡す必要があるため、トリガーコールバックで新しく挿入された値をどのように使用するかわかりません。

どうすればこれを達成できますか?

編集:私はそれを修正しました、アダムの答えのおかげで、誰かがそれを必要とする場合に備えて、これが作業バージョンです:

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

トリガー関数内では、NEW.column_nameを使用して、新しく挿入または更新された値を参照できます。逆に、OLD.column_nameは、更新/削除前の値を参照します。

詳細はこちら: https://www.postgresql.org/docs/current/static/sql-createtrigger.html

お役に立てば幸いです。

4
Adam B

トリガー関数内では、NEW.column_nameを使用して、新しく挿入または更新された値を参照できます。逆に、OLD.column_nameは、更新または削除前の値を参照します。

詳細はこちら: https://www.postgresql.org/docs/current/static/sql-createtrigger.html

お役に立てば幸いです。

1
ankit