CREATE [ OR REPLACE ] RULE name AS ON event TO table [ WHERE condition ] DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }
CREATE RULEにより、指定したテーブルまたはビューに適用するルールを新しく定義できます。 CREATE OR REPLACE RULEを使用すると、ルールを新しく作成するか、同じテーブルの同じ名前の既存ルールを置き換えるかのいずれかを実行します。
PostgreSQLのルールシステムによって、データベーステーブルに対する挿入、更新、削除の代替として行われるアクションを定義することができます。 大雑把にいうと、指定されたテーブルに指定されたコマンドが実行された時に、ルールによって実行されるコマンドが追加されます。 その他にも、INSTEADルールによって指定されたコマンドを他のコマンドに置き換えることも、全くコマンドを実行させないようにすることも可能です。 ルールはテーブルビューを実装するためにも使われます。 ルールは本当にコマンドを変換する機構、もしくは、コマンドマクロであることを認識することが重要です。 この変換はコマンドの実行が始まる前に発生します。 実際に各物理行に独立した操作を行いたい場合、おそらくルールではなくトリガを使用することでしょう。 ルールシステムについての詳細は、第33章に記載されています。
現時点では、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以外は、どのテーブルも参照できません。 また、集約関数を含めることもできません。
INSTEADは、元のコマンドの代わりにこのコマンドが実行されることを示します。
ALSOは元のコマンドに加えてこのコマンドが実行されることを示します。
ALSOもINSTEADも指定されなかった場合、ALSOがデフォルトです。
ルールのアクションを構成する単一または複数のコマンドです。 有効なコマンドは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 ALSO NOTIFY mytable; UPDATE mytable SET name = 'foo' WHERE id = 42;
では、id = 42という条件に一致する行があってもなくても、1つのNOTIFYイベントがUPDATEの際に送信されます。 これは実装上の制限であり、将来のリリースでは修正されるかもしれません。