CREATE RULE name AS ON event TO object [ WHERE condition ] DO [ INSTEAD ] [ action | NOTHING ]
作成するルール名。
イベントとは、select、 update、delete、 insert のいずれかです。
オブジェクトとは、 table もしくは table.column のいずれかです。
任意の SQL WHERE 句であり、SQL においてインスタンス変数を 記述できる所であれば、インスタンス変数の代わりに new や old を使用す ることができます。
任意の SQL 文であり、SQL においてインスタンス変数を 記述できる所であれば、インスタンス変数の代わりに new や old を使用す ることができます。
Postgres の ルールシステム を使用して、データベー ステーブルやクラスに対する挿入、更新、削除時に実行される別の 動作を定義することができます。 現在、テーブルのビューを実装するためにルールが使用されています。
ルールにおいては、個々のインスタンスがアクセス、挿入、更新、 削除される時点では (選択、更新、削除の場合) 古いインスタンス と (挿入、更新の場合) 新しいインスタンスが存在すると想定しま す。 古いインスタンスに対して、ON 句にて指定された event と WHERE 句にて指定された condition が真と なる場合、ルールの action 部分が実 行されます。 しかし、まず、古いインスタンスと新しいインスタンスの両方、も しくは片方のフィールドの値が old.attribute-name と new.attribute-name に代入されます。
ルールの action 部分は、その起動元となったユーザコマンドと同じコマンドとトラ ンザクション識別子で実行します。
SQL ルールにおいて注意しなければならないのは順番です。 同じクラス名やインスタンス変数がルールの event、 condition、 action 部分にある場合、それらは全て別のタプル変数とみなされます。 より正確にいうと、new と old だけはこれらの句の間で共有される タプル変数です。 例えば、以下の2 つの例は同じ意味を持ちます。
ON UPDATE TO emp.salary WHERE emp.name = "Joe" DO UPDATE emp SET ... WHERE ...
ON UPDATE TO emp-1.salary WHERE emp-2.name = "Joe" DO UPDATE emp-3 SET ... WHERE ...各ルールは省略可能な INSTEAD タグを持つことができます。 このタグがなければ、 action は、ルールの condition 部分において event が起こった時、ユーザコマンドに続いて実行されます。 もしあれば、 action はユーザコマンドの代わりに実行されます。 後者の場合、 action を NOTHING キーワードにすることが できます。
ルールの循環を防ぐことに注意することは非常に重要です。 例えば、次の 2 つのルール定義はどちらも Postgres で受け付けられますが、 この select コマンドにより Postgres は、問い合わせがあまりに多く循環して実行されたことが原因 となったエラーを報告します。
Example 19-1. 循環する書き換えルールの組合せの例
CREATE RULE bad_rule_combination_1 AS ON SELECT TO emp DO INSTEAD SELECT TO toyemp;
CREATE RULE bad_rule_combination_2 AS ON SELECT TO toyemp DO INSTEAD SELECT TO emp;
EMP から選択を行なうと、このルールにより Postgres は、問い合わせがあまり に多く循環して実行されたことが原因となったエラーを発生します。
SELECT * FROM emp;
あるクラスに対してルールを定義するためには、そのクラス にルール定義アクセス権限を持つ必要があります。 権限を変更する場合は、GRANT と REVOKE を使用して下さい。
SQL ルール内のオブジェクトは配列の参照 をとることができません。また、パラメータも持つことができ ません。
"oid" フィールドを除き、ルール内ではシステム属性を参照する ことはできません。 特に、これはルール内ではインスタンスの関数 (例えば foo(emp)、ここで emp はクラスです。)を呼び出すことができないことを意味しています。
ルールシステムはルールのテキストと問い合わせ計画をテキス ト属性として保持しています。 これは、ルールとその各種内部表現が 1 ページ (8KB) 程度の 何らかの値を越えた場合にルールの作成に失敗する可能性が あることを意味します。
Sam が Joe と同じ給与調整を受けるようにします。
CREATE RULE example_1 AS ON UPDATE emp.salary WHERE old.name = "Joe" DO UPDATE emp SET salary = new.salary WHERE emp.name = "Sam";Joe が給与調整を受けとった時点で、このイベントが真にな り、Joe の古いインスタンスと提出された新しいインスタン スが実行処理部分で使用可能になります。 従って、彼の新しい給与は続いて実行されるルールの動作部 分に代入されます。 これにより Joe の給与は Sam に伝わります。
Bill が給与にアクセスした時に Joe の給与を参照するよう にします。
CREATE RULE example_2 AS ON SELECT TO EMP.salary WHERE old.name = "Bill" DO INSTEAD SELECT emp.salary FROM emp WHERE emp.name = "Joe";
Joe が靴部門の従業員の給与にアクセスできないようにし ます。 (current_user は現在のユーザ名 を返します。)
CREATE RULE example_3 AS ON SELECT TO emp.salary WHERE old.dept = "shoe" AND current_user = "Joe" DO INSTEAD NOTHING;
玩具部門で働く従業員というビューを作成します。
CREATE toyemp(name = char16, salary = int4); CREATE RULE example_4 AS ON SELECT TO toyemp DO INSTEAD SELECT emp.name, emp.salary FROM emp WHERE emp.dept = "toy";
全従業員の給与が 5000以下となるようにします。
CREATE RULE example_5 AS ON INERT TO emp WHERE new.salary > 5000 DO UPDATE emp SET salary = 5000 WHERE emp.oid = new.oid;