0
0

More than 1 year has passed since last update.

PostgreSQLチート・データベース関数

Last updated at Posted at 2022-08-22

公式

やりたいこと

2 つやってみたいことがあります

  • updated_at を項目として持っているテーブルは update トリガーで function を起動して updated_at に現在日時をセットする
  • ユーザが更新可能なテーブルはすべて update と delete トリガーで function を起動して更新前のレコードを別テーブルに履歴として保存する

supabase 公式

updated_at に現在日時をセット

戦略

updated_at を持つテーブルに対して、update データベーストリガーを設定し、トリガーからトリガ関数を呼び出す。トリガ関数では、updated_at に現在日時をセットする

create or replace function

create or replace function set_updated_at()
returns trigger
language plpgsql
as $$
begin
  new.updated_at := now();
  return new;
end;
$$
  • トリガ関数は create function コマンドを使って returns trigger という戻り値の型を持った引数のない関数として定義する
  • new は RECORD 型のデータ型で、update操作によって更新された新しい行を保持している
  • 詳しくは PostgreSQL公式 を参照

create trigger

create trigger trg_cats_updated_at before update on cats for each row execute procedure set_updated_at();

動作確認

  • function と trigger を SQL Editor から投入
  • Table Editor で cats テーブルの適当なレコードの name を更新
  • updated_at に日時 (UTC) がセットされる

履歴

戦略

ユーザが更新可能なテーブルに対して、update と delete データベーストリガーを設定し、トリガーからトリガ関数を呼び出す。トリガ関数では、update または delete 前のデータレコードイメージと created_log_at に現在日時をセットする

create or replace function

create or replace function add_profiles_log()
returns trigger
language plpgsql
as $$
declare
  delete_col boolean := false;
begin
  if (TG_OP = 'DELETE') then
    delete_col := true;
  end if;
  insert into profiles_log (
    id, created_log_at, delete, created_at, updated_at, username
    , avatar_url, plan, contact_madd, year_of_birth, zip
    , job, facebook, twitter, homepage, blog, gender, score
  ) values (
    old.id, now(), delete_col, old.created_at, old.updated_at, old.username
    , old.avatar_url, old.plan, old.contact_madd, old.year_of_birth
    , old.zip, old.job, old.facebook, old.twitter, old.homepage
    , old.blog, old.gender, old.score
  );
  return new;
end;
$$
  • TG_OP は「textデータ型。 トリガを発行した操作を示す、INSERT、UPDATEまたはDELETEという文字列」ということなので、ここが DELETE の時は delete_col := true; にしています
  • old には更新前のレコードイメージが保持されているので、これを profiles_log にセットしています

create trigger

create trigger trg_profiles_update before update or delete on profiles for each row execute procedure add_profiles_log();

動作確認

  • function と trigger を SQL Editor から投入
  • Table Editor で profiles テーブルの適当なレコードの username を更新
  • 更新前の username で profiles_log に新規レコードがセットされる (delete は false)
  • Table Editor で profiles テーブルの適当なレコードを削除する
  • 削除前のレコードイメージで新規レコードがセットされる (delete は true)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0