CREATE RULE — 新しい書き換えルールを定義する
CREATE [ OR REPLACE ] RULEname
AS ONevent
TOtable_name
[ WHEREcondition
] DO [ ALSO | INSTEAD ] { NOTHING |command
| (command
;command
... ) } ここでevent
は以下のうちの1つです。 SELECT | INSERT | UPDATE | DELETE
CREATE RULE
により、指定したテーブルまたはビューに適用するルールを新しく定義できます。
CREATE OR REPLACE RULE
を使用すると、新しいルールの作成、または、同じテーブルの同じ名前の既存ルールの置き換えのいずれかを実行します。
PostgreSQLのルールシステムを使用すると、データベーステーブルに対する挿入、更新、削除時に本来の操作の代替として実行するアクションを定義できます。
簡単に言えば、指定されたテーブルに対して指定されたコマンドが実行された時、ルールによって追加のコマンドが実行されるということです。
その他にも、INSTEAD
ルールによって指定されたコマンドを他のコマンドに置き換えたり、まったくコマンドを実行しないようにすることも可能です。
また、ルールはSQLビューを実装するためにも使われます。
重要なのは、ルールとは実際にコマンドを変換する仕組み、言い換えれば、コマンドのマクロであることです。
ルールによる変換はコマンドの実行前に発生します。
各物理行を個別に操作したい場合、ルールではなくトリガを使用する方が良いでしょう。
ルールシステムについての詳細は、38章ルールシステムに記載されています。
現時点では、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
問い合わせのサポートがうまく動作しません。)
十分単純であり自動更新可能なビュー(CREATE VIEW参照)は、更新可能とするためにユーザ作成のルールを必要としません。 とにかく明示的なルールを作成することもできますが、自動更新による変形は明示的なルールよりも通常高速です。
検討すべき別の方法は、ルールの代わりにINSTEAD OF
トリガ(CREATE TRIGGER参照)を使うことです。
name
作成するルールの名前です。 この名前は、同じテーブルの他のルールとは異なる名前にする必要があります。 同一テーブルにイベントの種類が同じルールが複数あった場合、ルール名の順番(アルファベット順)に適用されます。
event
イベントとは、SELECT
、INSERT
、UPDATE
、DELETE
のいずれかです。
ON CONFLICT
句を含むINSERT
は、INSERT
ルールまたはUPDATE
ルールのあるテーブルに対して使えないことに注意してください。
代わりに、更新可能ビューを利用することを検討してください。
table_name
ルールを適用するテーブルまたはビューの名前です(スキーマ修飾名も可)。
condition
任意のSQL条件式です(boolean
型を返します)。
条件式では、NEW
およびOLD
以外のテーブルは参照できません。
また、集約関数を含めることもできません。
INSTEAD
INSTEAD
は、元のコマンドの代わりにこのコマンドが実行されることを示します。
ALSO
ALSO
は元のコマンドに加えてこのコマンドが実行されることを示します。
ALSO
もINSTEAD
も指定されなかった場合、ALSO
がデフォルトです。
command
ルールのアクションを構成する単一または複数のコマンドです。
有効なコマンドは、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
イベントが送信されます。
これは実装上の制限であり、将来のリリースでは修正されるかもしれません。
CREATE RULE
はPostgreSQLの言語拡張で、問い合わせ書き換えシステム全体が言語拡張です。