CREATE RULE

Name

CREATE RULE  -- 新しい書き換えルールの定義

Synopsis

CREATE [ OR REPLACE ] RULE name AS ON event
    TO table [ WHERE condition ]
    DO [ INSTEAD ] action

ここで action は以下のとおりです。

NOTHING
| query
| ( query ; query ... )
  

入力

name

作成するルールの名前です。 この名前は、同じテーブルの他のルールとは異なる名前にする必要があります。

event

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

table

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

condition

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

query

actionを構成する単数または複数の問い合わせは、任意のSQL SELECTINSERTUPDATEDELETENOTIFY文のどれでも構いません。

conditionaction の内部では、特別なテーブル名 newold は参照されるテーブルの値を参照するために使用できます。 new は、ON INSERT と ON UPDATE ルールで、挿入または更新されている新しい行を参照するのに有効です。 old は、ON UPDATE と ON DELETE ルールで、更新または削除されている既存の行を参照するのに有効です。

出力

CREATE RULE

ルールの作成に成功すると返されるメッセージです。

説明

CREATE RULE により、指定したテーブルまたはビューに適用するルールを新しく定義できます。 CREATE OR REPLACE RULE を使用すると、ルールを新しく作成するか、同じテーブルの同じ名前の既存ルールを置き換えるかのいずれかを実行します。

PostgreSQLルールシステムによって、データベーステーブルの挿入、更新、削除の代替として行われるアクションを定義することができます。ルールはテーブルビューを実装するためにも使われます。

ルールの語義は個別のインスタンス(行)がアクセスされ、挿入、更新、削除される場合、古いインスタンス(選択、更新、削除の対象)と、新しいインスタンスが(更新と追加の対象)存在するということです。 与えられたイベント型と対象テーブルのすべてのルールは、逐次 (名前順で) 審査されます。WHERE句(存在する場合)で指定されたconditionが真である場合、そのルールのaction部分が実行されます。INSTEADが指定されると、元の問い合わせの代わりに actionが行われます。 そうでない場合、 ON INSERT の場合は元の問い合わせの後に、 ON UPDATE や ON DELETE の場合は元の問い合わせの前に行なわれます。conditionactionの両方のなかで、 古いインスタンスあるいは新しいインスタンスの中のフィールドの値は old.attribute-namenew.attribute-name に代入されます。

ルールのaction部分は、1つ以上の問い合わせを持つことができます。 複数の問い合わせを記述するには、カッコで囲んでください。 そのような問い合わせは、指定された順序で処理されます。actionは動作が何もないことを示すためにNOTHINGを使うこともできます。したがって、DO INSTEAD NOTHINGルールは(その条件が真の場合)元の問い合わせの実行を抑制します。 DO NOTHING ルールはなにもしません。

ルールのaction部分は動作を促したユーザコマンドと同じコマンドとトランザクション識別子で実行します。

ルールは、実は問い合わせの変換メカニズム、または問い合わせのマクロであるということを理解しておく必要があります。 問い合わせ全体が処理され、ルールアクションを含む一連の問い合わせに変換されます。 この処理は、問い合わせの評価が始まる前に実行されます。 したがって、条件付きルールは、そのルールから派生したアクションの WHERE 句にルール条件を追加することで操作されます。 上記のように、ルールが各行について実行する操作であると説明することは、多少誤解を招きやすいと言えます。 実際に、物理的な各行で独立して実行する操作が必要な場合は、おそらくルールではなくトリガを使用すべきでしょう。 ルールは、処理されている特定のデータと無関係に、問い合わせ全体を独立して変換する必要がある状況で、最も有用です。

ルールとビュー

現時点では、ON SELECTルールは無条件のINSTEADルールでなければならず、単一SELECT問い合わせで成り立つアクションを持っていなければなりません。 このようにして、ON SELECT ルールはテーブルを効果的にビューに変え、そのビューの可視的な内容は (もしあったとしても) テーブル内に格納されているものではなく、ルールの SELECT 問い合わせによって返された行です。実際のテーブルを作成しそれにON SELECTルールを定義するよりは CREATE VIEWコマンドを書く方がよい形式とされています。

CREATE VIEW は(背後の格納領域が不要な)ダミーのテーブルを作成し、それに ON SELECT ルールを関連づけます。システムは、実際のテーブルがどこにあるのかを判断できないため、ビューに対する更新を許可しません。ON INSERT、ON UPDATE、ON DELETE ルール(もしくは、目的に応じてこのうちの一部)を定義して、ビューへの更新操作を他のテーブルへの適切な更新操作に置換することで、更新可能なビューという幻を作成することができます。

ビューの更新の際に条件付きルールの使用を予定している場合、わながあります。そのビューに許可したい操作それぞれに無条件 INSTEAD ルールを用意する 必要があることです。ルールが条件付き、または、INSTEAD ではない場合、システムは更新操作の試行を拒絶します。 その場合ダミーテーブルへの操作を行なうことになるとシステムがみなすからです。条件付きルール内で全ての使用し得るケースを扱うのであれば、無条件の DO INSTEAD NOTHING ルールを追加し、システムにダミーテーブルへの更新を行なうことが決してないことを理解させることで、それを実現することができます。さらに、INSTEAD でない条件付きルールを作成します。 これらが起動されるところでは、デフォルトのINSTEAD NOTHING 動作に追加されます。

注釈

テーブルにルールを定義するためには、ルール定義アクセス権を持っていなければなりません。権限を変えるにはGRANTREVOKEを使います。

循環ルールを避けるために注意を払うことはとても重要です。たとえば、下記の2つのルールそれぞれがPostgreSQLに受け入れられた場合、SELECTコマンドは、問い合わせが何度も循環しすぎたためにPostgreSQLにエラーを表示させます。

CREATE RULE "_RETURN" AS
    ON SELECT TO emp
    DO INSTEAD
	SELECT * FROM toyemp;

CREATE RULE "_RETURN" AS
    ON SELECT TO toyemp
    DO INSTEAD
	SELECT * FROM emp;

以下ように EMP から選択しようとすると、問い合わせが何度も循環しすぎるため、PostgreSQL でエラーが発生する原因となります。

SELECT * FROM emp;

現在、ルールが 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 である行があるかどうかに関わらず、UPDATE の間に 1 つの NOTIFY イベントが 送信されます。 これは、今後のリリースで修正される可能性のある実装制限です。

互換性

SQL92

CREATE RULEPostgreSQL の言語拡張です。SQL92にはCREATE RULEはありません。