CREATE [ OR REPLACE ] RULE name AS ON event TO object [ WHERE condition ] DO [ INSTEAD ] action 这里 action 可以是: NOTHING | query | ( query ; query ... )
创建的规则名.
事件是 SELECT, UPDATE,DELETE 或 INSERT 之一.
对象是 table 或 table.column. (目前只有 table 形式实际上是实现了的.
任意 SQL 条件表达式(返回 boolean).条件表达式除了引用 new 和 old 之外不能引用任何表.
组成 action 的查询可以是任何 SQL SELECT,INSERT, UPDATE,DELETE,或 NOTIFY 语句之一.
在 condition 和 action 里, 特殊表名字 new 和 old 可以用于指向引用表 ( object) 里的数值 new 在 ON INSERT 和 ON UPDATE 规则里 可以指向被插入或更新的新行. old 在 ON UPDATE,和 ON DELETE 规则里可以指向现存的被更新,或者删除的行.
CREATE RULE 定义一个适用于特定表或者视图的新规则。 CREATE OR REPLACE RULE 要么是创建一个新规则, 要么是用一个同表上的同名规则替换现有规则。
PostgreSQL 规则系统 允许我们在从数据库或表中更新, 插入或删除东西时定义一个可选的动作来执行。目前,规则用于实现表视图。
规则的语意是在一个单独的记录正被访问,更新,插入或删除时, 将存在一个旧记录(用于检索,更新和删除)和一个新记录 (用于更新和追加). 这时给定事件类型和给定目标对象(表)的所有规则都将被检查, (顺序不定). 如果在 WHERE (如果有)子句里面所声明的 condition� 为真,那么 action 部分的规则就被执行. 如果声明了 INSTEAD,那么 action 就会代替原来的查询;否则,如果是 ON INSERT 那么它在原来的查询之后 执行,如果是 ON UPDATE 或者 ON DELETE,那么它在原来的查询之前执行. 在 condition 和 action 里面, 在旧记录里字段的数值和/或新记录里字段的数值被 old. attribute-name 和 new. attribute-name 代替.
规则的 action 部分可以由一条或者多条查询组成.要写多个查询,用圆括弧 把它们包围起来. 这样的查询将以声明的顺序执行(只是我们不能保证 对一个对象的多个规则的执行顺序). action 还可以是 NOTHING 表示没有动作.因此,一个 DO INSTEAD NOTHING 规则制止了 原来的查询的运行(当条件为真时); DO NOTHING 规则是没有用的.
规则的 action 部分 执行的时候带有和触发动作的用户命令相同的命令和事务标识符.
目前,ON SELECT 规则必须是无条件的 INSTEAD 规则并且 必须有一个由一条 SELECT 查询组成的动作. 因此,一条 ON SELECT 规则有效地把对象表转成视图,它的可见内容 是规则的 SELECT 查询返回的记录而不是存储在表中的内容(如果有的话). 我们认为写一条 CREATE VIEW 命令比创建一个表然后定义一条 ON SELECT 规则在上面的风格要好.
CREATE VIEW 创建一个虚拟表(没有下层的存储) 以及相关的 ON SELECT 规则.系统不允许对视图进行更新, 因为它知道在视图上没有真正的表.你可以创建一个可以更新的视图的幻觉, 方法是在视图上定义 ON INSERT,ON UPDATE,和 ON DELETE 规则 (或者满足你需要的任何上述规则的子集),用合适的对其它表的更新替换 在视图上更新的动作.
如果你想在视图更新上使用条件规则,那么这里就有一个补充∶ 对你希望在视图上允许的每个动作,你都必须有一个 无条件的 INSTEAD 规则.如果规则是有条件的,或者它不是 INSTEAD, 那么系统仍将拒绝执行更新动作的企图,因为它认为它最终会在某种 程度上在虚拟表上执行动作. 如果你想处理条件规则上的所由有用的情况,那也可以;只需要增加 一个无条件的 DO INSTEAD NOTHING 规则确保系统明白它将决不会被 调用来更新虚拟表就可以了.然后把条件规则做成非 INSTEAD; 在这种情况下,如果它们被触发,那么它们就增加到缺省的 INSTEAD NOTHING 动作中.
为了在表上定义规则,你必须有规则定义权限. 用 GRANT 和 REVOKE 修改权限.
有一件很重要的事情是要避免循环规则. 比如,尽管下面两条规则定义都是 PostgreSQL 可以接受的, select 命令会导致 PostgreSQL 报告 一条错误信息,因为该查询循环了太多次:
CREATE RULE bad_rule_combination_1 AS ON SELECT TO emp DO INSTEAD SELECT * FROM toyemp; CREATE RULE bad_rule_combination_2 AS ON SELECT TO toyemp DO INSTEAD SELECT * FROM emp;
下面这个对EMP的查询企图将导致 PostgreSQL 产生一个错误信息, 因为该查询循环了太多次:
SELECT * FROM emp;
目前,如果一个规则包含一个 NOTIFY 查询,那么该 NOTIFY 将被 无条件执行 --- 也就是说,如果规则不施加到任何行上头, 该 NOTIFY 也会被发出.比如,在
CREATE RULE notify_me AS ON UPDATE TO mytable DO NOTIFY mytable; UPDATE mytable SET name = 'foo' WHERE id = 42;
里,一个 NOTIFY 事件将在 UPDATE 的时候发出,不管是否有某行的 id = 42.这是一个实现的限制,将来的版本应该修补这个毛病.