format()
を使用できます 識別子とリテラルを自動的に正しく処理するため、動的SQLクエリの作成がはるかに簡単になります。人々が通常見落としていることの1つは、(...).*
を使用して、単一のレコード式をそのすべての列に展開できることです。 -これはNEW
でも機能します およびOLD
トリガーに変数を記録します。例: select (new).*
using
execute
のキーワード 声明。レコードとテキスト表現の間でレコードを相互に変換する必要はありません。
その可能性を使用して、トリガー関数を次のように簡略化できます。
DECLARE
l_sql text;
BEGIN
IF TG_TABLE_SCHEMA = 'public' THEN
newtable := TG_TABLE_NAME || '_actividad';
ELSE
newtable := TG_TABLE_SCHEMA || '_' || TG_TABLE_NAME || '_actividad';
END IF;
PERFORM creartablaactividad(TG_TABLE_SCHEMA, TG_TABLE_NAME);
l_sql := 'INSERT INTO actividad.%I SELECT current_user, current_timestamp, %L, ($1).*';
IF TG_OP = 'DELETE' THEN
execute format(l_sql, newtable, 'D') using OLD;
RETURN OLD;
ELSE
-- covers UPDATE and INSERT
execute format(l_sql, newtable, 'U') using NEW;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
%I
のようなプレースホルダーを使用する および%L
また、実際のSQLを一度だけ定義して再利用することもできます。これらの「パラメータ」は、format()
に置き換えられます。 関数($1
を保持します )
($1).*
の使用に注意してください SQL文字列内。これにより、execute
が作成されます ステートメントは、レコードパラメータ$1
を展開します そのすべての列に。レコード自体は、USING
で「ネイティブに」渡されます キーワード。
INSERT
の使用 ターゲット列リストなし(insert into some_table ...
insert into some_table (col1, col2, ...) ...
)はかなり壊れやすいことです。ソースとターゲットが一致しない場合、挿入は非常に簡単に失敗する可能性があります。 。
監査テーブルで大規模なレポートを実行しない場合(明示的な列名を使用する方がはるかに効率的です)、JSON
を使用したより一般的な監査トリガーを検討することをお勧めします。 またはHSTORE
レコード全体を格納する列。利用可能な既製の監査トリガーがいくつかあります:
- http://okbob.blogspot。 de / 2015/01 / most-simply-implementation-of-history.html
- https://github.com/wingspan/wingspan-auditing
- https://www.cybertec-postgresql.com / en / tracking-changes-in-postgresql /
- https://wiki.postgresql.org/wiki/Audit_trigger_91plus