CREATE RULE

Name

CREATE RULE  --  新しいルールを定義する。

Synopsis

CREATE RULE name AS ON event
    TO object [ WHERE condition ]
    DO [ INSTEAD ] [ action | NOTHING ]
  

入力

name

作成するルール名。

event

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

object

オブジェクトとは、 table もしくは table.column のいずれかです。

condition

任意の SQL WHERE 句であり、SQL においてインスタンス変数を 記述できる所であれば、インスタンス変数の代わりに newold を使用す ることができます。

action

任意の SQL 文であり、SQL においてインスタンス変数を 記述できる所であれば、インスタンス変数の代わりに newold を使用す ることができます。

出力

CREATE

ルールの作成に成功した場合に返されるメッセージ。

説明

Postgresルールシステム を使用して、データベー ステーブルやクラスに対する挿入、更新、削除時に実行される別の 動作を定義することができます。 現在、テーブルのビューを実装するためにルールが使用されています。

ルールにおいては、個々のインスタンスがアクセス、挿入、更新、 削除される時点では (選択、更新、削除の場合) 古いインスタンス と (挿入、更新の場合) 新しいインスタンスが存在すると想定しま す。 古いインスタンスに対して、ON 句にて指定された event と WHERE 句にて指定された condition が真と なる場合、ルールの action 部分が実 行されます。 しかし、まず、古いインスタンスと新しいインスタンスの両方、も しくは片方のフィールドの値が old.attribute-namenew.attribute-name に代入されます。

ルールの action 部分は、その起動元となったユーザコマンドと同じコマンドとトラ ンザクション識別子で実行します。

注意

SQL ルールにおいて注意しなければならないのは順番です。 同じクラス名やインスタンス変数がルールの eventconditionaction 部分にある場合、それらは全て別のタプル変数とみなされます。 より正確にいうと、newold だけはこれらの句の間で共有される タプル変数です。 例えば、以下の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 はユーザコマンドの代わりに実行されます。 後者の場合、 actionNOTHING キーワードにすることが できます。

ルールの循環を防ぐことに注意することは非常に重要です。 例えば、次の 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;
      

あるクラスに対してルールを定義するためには、そのクラス にルール定義アクセス権限を持つ必要があります。 権限を変更する場合は、GRANTREVOKE を使用して下さい。

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;
   

互換性

SQL92

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