CREATE RULE name AS ON event TO object [ WHERE condition ] DO [ INSTEAD ] [ action | NOTHING ]
规则的语意是在一个单独的记录正被访问,更新,插入或删除时,将存在一个旧记录(用于检索,更新和删除)和一个新记录(用于更新和追加).如果在 ON 子句里所声明的 event 和在 WHERE 语句里面所声明的 condition 对于旧记录都为真,那么action 部分的规则就被执行.但是,旧记录的各字段值和/或新记录将先用 current.attribute-name 和 new.attribute-name 取代.
规则 action 部分执行时的命令和事务标识与激活该规则的用户命令相同.
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;
一条 SQL 规则里的对象不能是一个数组引用和不能有参数。
除了 "oid" 字段,一个规则里任何地方都不能引用系统表属性。这意味着在规则里任何地方都不能调用实例/记录函数 (比如, "foo(emp)" 这里 "emp" 是一个表).
规则系统将规则文本和查询规划按文本(text)属性存储.这意味着当创建的规则加上各种其内部表达式超过一次存储页面请求的值(8KB)时,规则创建可能失败。
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;