web-dev-qa-db-ja.com

値を設定するためのPostgresql挿入トリガー

Postgresqlに、テーブルTがあり、その列の1つがC1であると仮定します。

新しいレコードがテーブルTに追加されたときに関数をトリガーしたい。この関数は、新しいレコードの列C1の値を確認し、null /空の場合、その値を'X'に設定する必要があります。

これは可能ですか?

49
user1408470

列のデフォルト値を設定しても機能しないため、トリガーが必要であることは正しいです。デフォルト値はnull値に対してのみ機能し、空白値の防止には役立ちません。

Postgresには、トリガーを作成するためのいくつかの手順があります。

ステップ1:タイプtriggerを返す関数を作成します。

CREATE FUNCTION my_trigger_function()
RETURNS trigger AS '
BEGIN
  IF NEW.C1 IS NULL OR NEW.C1 = '''' THEN
    NEW.C1 := ''X'';
  END IF;
  RETURN NEW;
END' LANGUAGE 'plpgsql'

ステップ2:beforeinsertを起動するトリガーを作成します。これにより、挿入される前に値を変更でき、上記の関数を呼び出します。

CREATE TRIGGER my_trigger
BEFORE INSERT ON T
FOR EACH ROW
EXECUTE PROCEDURE my_trigger_function()

これで完了です。

SQLFIddleで実行される上記のコード を参照してください。


コメントで、値'X'は、サブクエリから取得されます。その場合、関連する行を次のように変更します。

NEW.C1 := (select some_column from some_table where some_condition);
77
Bohemian

可能ですが、代わりに列にデフォルトの制約を設定する方が良いでしょう。次のような表を作成する場合:

create table mytable as (
    C1 thetype not null default X
);

これは、テーブルに行を追加し、C1の値を指定しない場合、代わりにXが使用されることを示しています。 not nullは必要ありませんが、更新がその列をnullにすることを防ぎます。

編集:これは定数Xに対してのみ機能します、あなたのコメントから、2つの可能な解決策があるようです。

トリガーを使用すると、次のようになります。

create function update_row_trigger() returns trigger as $$
begin
    if new.C1 is NULL then
        new.C1 := X;
    end if;
    return new;
end
$$ language plpgsql;

create trigger mytrigger before insert on mytable for each row execute procedure update_row_trigger();

トリガー関数のnew変数は特別であり、挿入される行を表します。トリガーをbefore insertトリガーとして指定すると、テーブルに書き込まれる前に行を変更できます。

2番目の解決策は、Postgresが異常な方法で定義する計算列を使用することです。

create or replace function C1(row mytable) returns columntype immutable as $$
begin
    return X; -- where X is an expression using values from `row`
end
$$ language plpgsql;

これにより、テーブルの行を取得して値を返す関数が作成され、を使用して呼び出すことができます。ただし、できることを意味します:

select
    *,
    t.C1
from
    mytable t;

不変の関数の宣言はオプションですが、「列」にインデックスを付ける場合に必要です。この列に次のようにインデックスを付けることができます。

create index on mytable (C1(mytable));
9
Steve