CREATE RULE
CREATE RULE — 定义一条新规则
大纲
CREATE RULEnameAS ONeventTOobject[ WHEREcondition] DO [ INSTEAD ] [action| NOTHING ]
输入
name要创建的规则的名称。
event事件是
select、update、delete或insert之一。objectObject 是
table或table.column。condition任意的 SQL WHERE 子句。只要 SQL 中允许出现实例变量,
new或current就可以出现在实例变量的位置上。action任意的 SQL 语句。只要 SQL 中允许出现实例变量,
new或current就可以出现在实例变量的位置上。
输出
- →
CREATE 规则成功创建时返回的消息。
描述
一条规则的语义是:当单个实例被访问、更新、插入或删除时,会有一个当前实例(对于检索、更新和删除)和一个新实例(对于更新和追加)。如果 ON 子句中指定的 event
和 WHERE 子句中指定的
condition 对当前实例为真,该规则的
action 部分就会被执行。不过首先,当前实例和/或新实例中字段的值会替换到
current.attribute-name
和 new.attribute-name 上。
规则的 action 部分与触发激活它的用户命令使用相同的命令标识符和事务标识符执行。
注解
关于 SQL 规则有一点需要提醒。如果同一个类名或实例变量出现在规则的
event、condition 和
action 部分中,它们都会被视为不同的元组变量。更准确地说,new 和 current 是这些子句之间仅有的共享元组变量。例如,下面的两条规则具有相同的语义:
on update to EMP.salary where EMP.name = "Joe"
do update EMP ( ... ) where ...
on update to EMP-1.salary where EMP-2.name = "Joe"
do update EMP-3 ( ... ) where ...
每条规则都可以带可选的 INSTEAD 标记。如果没有该标记,当规则
condition 部分中的
event
发生时,action 会随用户命令一起执行。或者,action 部分也可以替代用户命令执行。在后一种情况下,action 可以是关键字
NOTHING。
在为一个特定的规则应用选择重写规则系统还是实例规则系统时,请记住:在重写系统中,current 指的是一个关系和一些限定词,而在实例系统中它指的是一个实例(元组)。
特别需要注意,重写规则系统既不会检测也不会处理循环规则。例如,尽管下面两条规则定义中的每一条都被 Postgres 接受,但 retrieve 命令会导致 Postgres 崩溃:
例 19.1. 循环重写规则组合的例子。
create rule bad_rule_combination_1 is
on select to EMP
do instead select to TOYEMP
create rule bad_rule_combination_2 is
on select to TOYEMP
do instead select to EMP
这个从 EMP 中检索的尝试会导致 Postgres 崩溃。
select * from EMP
要在一个类上定义规则,你必须拥有该类的规则定义权限。使用 GRANT
和 REVOKE 来更改权限。
用法
让 Sam 获得与 Joe 相同的薪水调整:
create rule example_1 is
on update EMP.salary where current.name = "Joe"
do update EMP (salary = new.salary)
where EMP.name = "Sam"
在 Joe 接受薪水调整时,该事件将变为真,并且 Joe 的当前实例和提议的新实例对执行例程可用。因此,他的新薪水会被代入该规则的 action 部分,随后被执行。这样就把 Joe 的薪水传播给了 Sam。
让 Bill 在访问时获得 Joe 的薪水:
create rule example_2 is
on select to EMP.salary
where current.name = "Bill"
do instead
select (EMP.salary) from EMP
where EMP.name = "Joe"
拒绝 Joe 访问鞋部门员工的薪水(current_user 返回当前用户的名称):
create rule example_3 is
on select to EMP.salary
where current.dept = "shoe" and current_user = "Joe"
do instead nothing
创建一个在玩具部门工作的员工的视图。
create TOYEMP(name = char16, salary = int4)
create rule example_4 is
on select to TOYEMP
do instead
select (EMP.name, EMP.salary) from EMP
where EMP.dept = "toy"
所有新员工的薪水必须不超过 5,000
create rule example_5 is
on insert to EMP where new.salary > 5000
do update newset salary = 5000
缺陷
SQL 规则中的对象不能是数组引用,也不能带参数。
除 "oid" 字段外,系统属性不能在规则中的任何地方被引用。这尤其意味着实例的函数(例如 "foo(emp)",其中
"emp" 是一个类)不能在规则中的任何地方被调用。
规则系统将规则文本和查询计划存储为文本属性。这意味着如果规则加上其各种内部表示超过大约一页(8KB)的某个值,规则的创建可能会失败。
兼容性
CREATE RULE 语句是 Postgres 的语言扩展。
SQL92
SQL92 中没有 CREATE RULE 语句。