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ルールによって指定されたコマンドを他のコマンドに置き換えたり、まったくコマンドを実行しないようにすることも可能です。 また、ルールはテーブルビューを実装するためにも使われます。 重要なのは、ルールとは実際にコマンドを変換する仕組み、言い換えれば、コマンドのマクロであることです。 ルールによる変換はコマンドの実行前に発生します。 各物理行を個別に操作したい場合、ルールではなくトリガを使用する方が良いでしょう。 ルールシステムについての詳細は、第37章に記載されています。
現時点では、ON SELECTルールは、条件を持たないINSTEADルールでなければなりません。また、ON SELECTルールが持つアクションは、単独のSELECTコマンドのみで構成される必要があります。 したがって、ON SELECTルールを使えば、効率的にテーブルをビューにすることができます。このビューでは、元のテーブルの内容ではなく、ルールに含まれるSELECTコマンドが返す行が、ビューの内容として提示されます。 ただし、テーブル自体を作成し、それにON SELECTルールを定義するよりは、CREATE VIEWコマンドを使用する方をお勧めします。
ON INSERT、ON UPDATE、ON DELETEルールを必要に応じて定義し、ビューに対する更新操作を他のテーブルに対する適切な更新操作に置換することで、更新可能なビューという実在しないオブジェクトを作成することができます。 INSERT RETURNINGなどをサポートしたければ、これらのルールに適切なRETURNING句を確実につけてください。
ビューの更新に条件付きルールを使用しようとする場合、落とし穴があります。 そのビューに許可するそれぞれの操作に、条件を持たないINSTEADルールを用意する必要があることです。 ルールが条件付きであったり、INSTEADでない場合、システムは更新操作を拒否します。 その場合、システムが、場合によっては、ビューのダミーテーブルに対する操作になる可能性があるとみなすからです。 使用する全てのケースについて条件付きルールを作成する場合は、条件を持たないDO INSTEAD NOTHINGルールを追加し、ダミーテーブルに対する更新は呼び出されないことをシステムに明示します。さらに、条件付きルールには、INSTEADと指定しないようにします。 これらの条件が満たされた場合、デフォルトのINSTEAD NOTHINGアクションにルールに含まれるアクションが追加されます。 (しかし現在、この方法ではRETURNING問い合わせのサポートがうまく動作しません。)
作成するルールの名前です。 この名前は、同じテーブルの他のルールとは異なる名前にする必要があります。 同一テーブルにイベントの種類が同じルールが複数あった場合、ルール名の順番(アルファベット順)に適用されます。
イベントとは、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ルールで有効です。更新または削除される既存の行を参照します。
テーブルにルールを定義する、または、そのルールを変更するためには所有者でなければなりません。
ビュー上のINSERT、UPDATE、DELETEルールでは、RETURNING句を追加して、ビューの列を返すことができます。 ルールがINSERT RETURNING、UPDATE RETURNING、DELETE RETURNINGコマンドによって呼び出された場合、この句は出力を計算することに使用されます。 RETURNINGなしでルールが呼び出された場合、ルールのRETURNING句は無視されます。 現在の実装では、無条件のINSTEADルールのみがRETURNINGを含むことができます。 さらに、同一イベント用のすべてのルールの中で多くても1つのRETURNING句を持つことができます。 (これにより確実に、結果を計算するために使用されるRETURNING句の候補が1つのみになります。) ビュー上のRETURNING問い合わせは、利用可能なルールすべてでRETURNINGが存在しない場合に拒絶されます。
ルールの循環は絶対に避けるよう注意してください。 例えば、下記の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という条件に一致する行があってもなくても、UPDATEの際、1つのNOTIFYイベントが送信されます。 これは実装上の制限であり、将来のリリースでは修正されるかもしれません。