CREATE RULE

名前

CREATE RULE -- 新しい書き換えルールを定義する

概要

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ルールによって指定されたコマンドを他のコマンドに置き換えたり、まったくコマンドを実行しないようにすることも可能です。 また、ルールはテーブルビューを実装するためにも使われます。 重要なのは、ルールとは実際にコマンドを変換する仕組み、言い換えれば、コマンドのマクロであることです。 ルールによる変換はコマンドの実行前に発生します。 各物理行を個別に操作したい場合、ルールではなくトリガを使用する方が良いでしょう。 ルールシステムについての詳細は、第35章に記載されています。

現時点では、ON SELECTルールは、条件を持たないINSTEADルールでなければなりません。また、ON SELECTルールが持つアクションは、単独のSELECTコマンドのみで構成される必要があります。 したがって、ON SELECTルールを使えば、効率的にテーブルをビューにすることができます。このビューでは、元のテーブルの内容ではなく、ルールに含まれるSELECTコマンドが返す行が、ビューの内容として提示されます。 ただし、テーブル自体を作成し、それにON SELECTルールを定義するよりは、CREATE VIEWコマンドを使用する方をお勧めします。

ON INSERTON UPDATEON DELETEルールを必要に応じて定義し、ビューに対する更新操作を他のテーブルに対する適切な更新操作に置換することで、更新可能なビューという実在しないオブジェクトを作成することができます。 INSERT RETURNINGなどをサポートしたければ、これらのルールに適切なRETURNING句を確実につけてください。

ビューの更新に条件付きルールを使用しようとする場合、落とし穴があります。 そのビューに許可するそれぞれの操作に、条件を持たないINSTEADルールを用意する必要があることです。 ルールが条件付きであったり、INSTEADでない場合、システムは更新操作を拒否します。 その場合、システムが、場合によっては、ビューのダミーテーブルに対する操作になる可能性があるとみなすからです。 使用する全てのケースについて条件付きルールを作成する場合は、条件を持たないDO INSTEAD NOTHINGルールを追加し、ダミーテーブルに対する更新は呼び出されないことをシステムに明示します。さらに、条件付きルールには、INSTEADと指定しないようにします。 これらの条件が満たされた場合、デフォルトのINSTEAD NOTHINGアクションにルールに含まれるアクションが追加されます。 (しかし現在、この方法ではRETURNING問い合わせのサポートがうまく動作しません。)

パラメータ

name

作成するルールの名前です。 この名前は、同じテーブルの他のルールとは異なる名前にする必要があります。 同一テーブルにイベントの種類が同じルールが複数あった場合、ルール名の順番(アルファベット順)に適用されます。

event

イベントとは、SELECTINSERTUPDATEDELETEのいずれかです。

table

ルールを適用するテーブルまたはビューの名前です(スキーマ修飾名も可)。

condition

任意のSQL条件式です(boolean型を返します)。 条件式では、NEWおよびOLD以外のテーブルは参照できません。 また、集約関数を含めることもできません。

INSTEAD

INSTEADは、元のコマンドの代わりにこのコマンドが実行されることを示します。

ALSO

ALSOは元のコマンドに加えてこのコマンドが実行されることを示します。

ALSOINSTEADも指定されなかった場合、ALSOがデフォルトです。

command

ルールのアクションを構成する単一または複数のコマンドです。 有効なコマンドは、SELECTINSERTUPDATEDELETENOTIFYです。

conditioncommandの内部では、対象とするテーブルの値を参照するために、特別なテーブル名NEWOLDを使用できます。 NEWは、ON INSERTON UPDATEルールで有効です。挿入または更新される新しい行を参照します。 OLDは、ON UPDATEON DELETEルールで有効です。更新または削除される既存の行を参照します。

注釈

テーブルにルールを定義する、または、そのルールを変更するためには所有者でなければなりません。

ビュー上のINSERTUPDATEDELETEルールでは、RETURNING句を追加して、ビューの列を返すことができます。 ルールがINSERT RETURNINGUPDATE RETURNINGDELETE 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イベントが送信されます。 これは実装上の制限であり、将来のリリースでは修正されるかもしれません。

互換性

問い合わせ書き換えシステム全体同様、CREATE RULEPostgreSQLの拡張です。