PostgreSQL9.1以降
format()
識別子をエスケープする方法が組み込まれています。以前よりもシンプル:
CREATE OR REPLACE FUNCTION foo_before()
RETURNS trigger AS
$func$
BEGIN
EXECUTE format('INSERT INTO %I.%I SELECT $1.*'
, TG_TABLE_SCHEMA, TG_TABLE_NAME || 'shadow')
USING OLD;
RETURN OLD;
END
$func$ LANGUAGE plpgsql;
VALUES
で動作します 式も。
db<>ここでフィドル
古いsqlfiddle。
主なポイント
-
format()
を使用する またはquote_ident()
識別子を(自動的に、必要な場合にのみ)引用することで、SQLインジェクションや単純な構文違反から保護します。
これは必要です 、自分のテーブル名でも! - スキーマ-テーブル名を修飾します。現在の
search_path
によって異なります ベアテーブル名を設定すると、別のスキーマにある同じ名前の別のテーブルに解決される可能性があります。 -
EXECUTE
を使用します 動的DDLステートメントの場合。 - 値を渡す
USING
で安全に 条項。 - plpgsqlでの動的コマンドの実行に関する詳細なマニュアルを参照してください。
-
RETURN OLD;
に注意してください トリガーにはトリガー機能が必要ですBEFORE DELETE
。詳細はこちらのマニュアルをご覧ください。
エラーメッセージが表示されます OLD
のため、ほぼ成功したバージョンで 表示されない EXECUTE
内 。また、試したように分解された行の個々の値を連結する場合は、quote_literal()
を使用してすべての列のテキスト表現を準備する必要があります。 有効な構文を保証します。また、知っている必要があります 事前に列名を処理して、システムカタログを照会します。これは、単純で動的なトリガー関数を使用するという考えに反します...
私のソリューションは、これらすべての合併症を回避します。また、少し簡略化されています。
PostgreSQL9.0以前
format()
まだ利用できないので:
CREATE OR REPLACE FUNCTION foo_before()
RETURNS trigger AS
$func$
BEGIN
EXECUTE 'INSERT INTO ' || quote_ident(TG_TABLE_SCHEMA)
|| '.' || quote_ident(TG_TABLE_NAME || 'shadow')
|| ' SELECT $1.*'
USING OLD;
RETURN OLD;
END
$func$ LANGUAGE plpgsql;
関連:
- PostgreSQL 8.2でTG_TABLE_NAMEを動的に使用するにはどうすればよいですか?