CREATE [ OR REPLACE ] RULE name AS ON event TO table [ WHERE condition ] DO [ INSTEAD ] { NOTHING | command | ( command ; command ... ) }
CREATE RULE により、指定したテーブルまたはビューに適用するルールを新しく定義できます。 CREATE OR REPLACE RULE を使用すると、ルールを新しく作成するか、同じテーブルの同じ名前の既存ルールを置き換えるかのいずれかを実行します。
PostgreSQLのルールシステムによって、データベーステーブルの挿入、更新、削除の代替として行われるアクションを定義することができます。 大雑把にいうと、指定されたテーブルに指定されたコマンドが実行された時に、ルールによって実行されるコマンドが追加されます。 その他にも、ルールによって、指定されたコマンドを他のコマンドに置き換えることも、まったくコマンドを実行させないようにすることも可能です。 ルールはテーブルビューを実装するためにも使われます。 ルールは本当にコマンドを変換する機構、もしくは、コマンドマクロであることを認識することが重要です。 この変換はコマンドの実行が始まる前に発生します。 実際に各物理行に独立した操作を行いたい場合、おそらくルールではなくトリガを使用することでしょう。 ルールシステムについてのより詳細は、第34章 に記載されています。
現時点では、ON SELECTルールは無条件のINSTEADルールでなければならず、単一SELECTコマンドで成り立つアクションを持っていなければなりません。 このようにして、ON SELECT ルールはテーブルを効果的にビューに変え、そのビューの可視的な内容は (もしあったとしても) テーブル内に格納されているものではなく、ルールの SELECT コマンドによって返された行です。 実際のテーブルを作成しそれにON SELECTルールを定義するよりは CREATE VIEWコマンドを書く方がよい形式とされています。
ON INSERT、ON UPDATE、ON DELETE ルール(もしくは、目的に応じてこのうちの一部)を定義して、ビューへの更新操作を他のテーブルへの適切な更新操作に置換することで、更新可能なビューという幻を作成することができます。
ビューの更新の際に条件付きルールの使用を予定している場合、罠があります。 そのビューに許可したい操作それぞれに無条件 INSTEAD ルールを用意する 必要があることです。 ルールが条件付き、または、INSTEAD ではない場合、システムは更新操作の試行を拒絶します。 その場合、ある条件でビューのダミーテーブルへの操作を行なうことになるとシステムがみなすからです。 条件付きルール内で全ての使用し得るケースを扱うのであれば、無条件の DO INSTEAD NOTHING ルールを追加し、システムにダミーテーブルへの更新を行なうことが決してないことを理解させることで、それを実現することができます。 さらに、INSTEAD でない条件付きルールを作成します。 これらが起動される条件では、デフォルトのINSTEAD NOTHING 動作に追加されます。
作成するルールの名前です。 この名前は、同じテーブルの他のルールとは異なる名前にする必要があります。 複数の同一テーブル、同一イベント種類のルールがあった場合、その名前のアルファベット順で適用されます。
イベントとは、SELECT、INSERT、UPDATE、DELETEのいずれかです。
ルールを適用するテーブルまたはビューの名前です (スキーマ修飾名でも可)。
任意の SQL 条件式です (boolean 型を返します)。 条件式では、new および old 以外は、どのテーブルも参照できません。 また、集約関数を含めることもできません。
ルールのアクションを構成する単数または複数のコマンドです。 有効なコマンドは SELECT、INSERT、UPDATE、DELETE、NOTIFY文です。
condition と command の内部では、特別なテーブル名 NEW と OLD は参照されるテーブルの値を参照するために使用できます。 NEW は、ON INSERT と ON UPDATE ルールで、挿入または更新されている新しい行を参照するのに有効です。 OLD は、ON UPDATE と ON DELETE ルールで、更新または削除されている既存の行を参照するのに有効です。
テーブルにルールを定義するためには RULE 権限が必要です。
循環ルールを避けるために注意を払うことはとても重要です。 たとえば、下記の2つのルールそれぞれがPostgreSQLに受け入れられた場合、SELECTコマンドは、問い合わせが何度も循環しすぎたためにPostgreSQLにエラーを表示させます。
CREATE RULE "_RETURN" AS ON SELECT TO t1 DO INSTEAD SELECT * FROM t2; CREATE RULE "_RETURN" AS ON SELECT TO t2 DO INSTEAD SELECT * FROM t1; SELECT * FROM t1;
現在、ルールが NOTIFY 問い合わせを含む場合、NOTIFY は無条件に実行されます。 つまり、ルールを適用すべき行が存在しなかったとしても、NOTIFY は発行されます。 例えば、
CREATE RULE notify_me AS ON UPDATE TO mytable DO NOTIFY mytable; UPDATE mytable SET name = 'foo' WHERE id = 42;
では、id = 42を持つ行があってもなくても、1つのNOTIFYイベントがUPDATEの際に送信されます。 これは実装上の制限であり、将来のリリースでは修正されるかもしれません。