Postgres の「パーティショニング」機能を使用するテーブルがいくつかあります。各テーブルに共通の BEFORE INSERT OF ROW トリガーを定義して、1) 親テーブルに対して挿入が発生した場合にパーティションを動的に作成し、2) パーティションに対して挿入を再実行します。
何かのようなもの:
CREATE OR REPLACE FUNCTION partition_insert_redirect( )
RETURNS trigger AS $BODY$
BEGIN
... create the new partition and set up the redirect Rules ...
/* Redo the INSERT dynamically. The new RULE will redirect it to the child table */
EXECUTE 'INSERT INTO ' || quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident(TG_TABLE_NAME) ||
' SELECT NEW.*'
END
しかし、「NEW」レコードは、EXECUTE SQL 内には表示されません。この作業をできるだけ簡単にするにはどうすればよいですか?
別の方法として、NEW レコードのフィールドを反復処理できますか?
私は一時テーブルを使用することを考えました:
EXECUTE 'CREATE TEMPORARY TABLE new_row (LIKE ' ||
quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident(TG_TABLE_NAME) ||
') ON COMMIT DROP';
INSERT INTO new_row SELECT NEW.*;
EXECUTE 'INSERT INTO ' || quote_ident(TG_TABLE_SCHEMA) || '.' || quote_ident(TG_TABLE_NAME) ||
' SELECT * FROM new_row';
DROP TABLE new_row;
しかし、一時テーブルへの参照がキャッシュされているため、これも機能しません: PL/PgSQL 関数で一時テーブルにアクセスすると、「OID ##### との関係が存在しません」というエラーが発生するのはなぜですか?
Postgres 8.2 を使用していますが、他のバージョンに変更できません。
EDIT:
@alvherreが指摘したように、これはおそらくEXECUTE ... USING構文を使用してPostgres 8.4で実行できます。http://wiki.postgresql.org/wiki/PL/pgSQL_Dynamic_Triggersの例を参照してください。