CREATE RULE

名称

CREATE RULE — 定义一个新规则

语法

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

输入

name
创建的规则名.
event
事件是 select, update, deleteinsert 之一.
object
对象是 tabletable.column.
condition
任何 SQL WHERE 语句.newcurrent 可以取代记录变量出现在任何 SQL 允许记录变量的地方.
action
任何 SQL 语句. newcurrent 可以取代记录变量出现在任何 SQL 允许记录变量的地方.

输出

CREATE
成功创建规则后的返回信息.

描述

Postgres 规则系统 允许我们在从数据库或表中更新,插入或删除东西时定义一个可选的动作来执行。目前,规则用于实现表视图。

规则的语意是在一个单独的记录正被访问,更新,插入或删除时,将存在一个旧记录(用于检索,更新和删除)和一个新记录(用于更新和追加).如果在 ON 子句里所声明的 event 和在 WHERE 语句里面所声明的 condition 对于旧记录都为真,那么action 部分的规则就被执行.但是,旧记录的各字段值和/或新记录将先用 current.attribute-namenew.attribute-name 取代.

规则 action 部分执行时的命令和事务标识与激活该规则的用户命令相同.

注意

一个关于 SQL 规则的注意事项是顺序.如果相同的表名或记录变量出现在规则的 event,conditionaction 部分.它们将会被认为是不同的记录变量.更准确地说,只有 newcurrent 在这些子句中共享记录变量.比如,下面两条规则有相同的语意:
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.

特别要指出的是重写(rewrite)规则系统既不检测也不执行循环规则.例如,尽管下面两条规则都被Postgres 所接受,检索命令将导致 Postgres 报错,因为该查询循环太多次:

例 19-1. 循环重写(rewrite)规则样例.

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" 是一个表).

规则系统将规则文本和查询规划按文本(text)属性存储.这意味着当创建的规则加上各种其内部表达式超过一次存储页面请求的值(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的当前记录和提供的新记录可被执行过程获得.因此,他的新薪水将代入动作部分,随后动作部分被执行.这样Sam的薪水就会和Joe的一样了.

当Bill访问数据库(薪水)时,令 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";
All new employees must make 5,000 or less
CREATE RULE example_5 AS
    ON INERT TO emp WHERE new.salary > 5000
    DO 
        UPDATE NEWSET SET salary = 5000;

兼容性

SQL92

CREATE RULE 语句是 Postgres 语言的扩展.在 SQL92 里没有 CREATE RULE 语句.