CREATE RULE

Name

CREATE RULE -- 定义一个新重写规则

Synopsis

CREATE [ OR REPLACE ] RULE name AS ON event
    TO table [ WHERE condition ]
    DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }

描述

CREATE RULE定义一个适用于特定表或者视图的新规则。 CREATE OR REPLACE RULE要么是创建一个新规则, 要么是替换一个表上的同名规则。

PostgreSQL规则系统允许在更新、插入、删除 时执行一个其它的预定义动作。简单的说,规则就是在指定表上执行指定动作 的时候,将导致一些额外的动作被执行。另外,一个INSTEAD 规则可以用另外一个命令取代特定的命令,或者令完全不执行该命令。规则 还可以用于实现表视图。规则实际上只是一个命令转换机制,或者说命令宏。 这种转换发生在命令开始执行之前。如果你想要针对每个物理行独立发生的操作, 那么可能应该使用触发器而不是规则。有关规则的更多信息可以在 Chapter 37找到。

目前,ON SELECT规则必须是无条件的 INSTEAD规则并且必须有一个由单独一条 SELECT查询组成的动作。因此,一条 ON SELECT规则有效地把表转成视图,它的 可见内容是规则的SELECT查询返回的记录而 不是存储在表中的内容。写一条CREATE VIEW 命令比创建一个表然后在上面定义一条ON SELECT 规则的风格要好。

你可以创建一个允许更新的视图的幻觉,方法是在视图上定义ON INSERTON UPDATEON DELETE规则 (或者满足你需要的任何上述规则的子集),用合适的对其它表的更新替换在视图上更新的动作。 如果打算支持INSERT RETURNING之类,就必须确保在规则的结尾放置恰当的RETURNING子句。

如果你想在视图更新上使用条件规则,那么这里就有一个补充:对你希望在视图上允许的每个动作, 你都必须有一个无条件的INSTEAD规则。如果规则是有条件的或者它不是INSTEAD, 那么系统仍将拒绝执行更新动作,因为它认为最终会在视图的虚拟表上执行这个动作。如果你想处理条件规则上的所有有用的情况, 那只需要增加一个无条件的DO INSTEAD NOTHING规则确保系统明白它决不会被调用来更新虚拟表就可以了。 然后把条件规则做成非INSTEAD;在这种情况下,如果它们被触发,那么它们就增加到缺省的INSTEAD NOTHING动作中。不过这种方法目前不支持RETURNING查询。

参数

name

创建的规则名。它必须在同一个表上的所有规则名字中唯一。同一个表上的同一个事件类型的规则是按照字母顺序运行的。

event

INSERTUPDATEDELETE事件之一。

table

规则作用的表或者视图的名字(可以有模式修饰)。

condition

任意返回booleanSQL条件表达式。条件表达式除了引用NEWOLD之外不能引用任何表,并且不能有聚集函数。

INSTEAD

指示使用该命令代替最初的命令。

ALSO

ALSO指示命令应该被执行,除了 初始命令。 该命令应该在最初的命令执行之后一起执行。

ALSOINSTEAD均未指定, 那么就默认为ALSO。 如果既没有声明ALSO也没有声明 INSTEAD,那么ALSO是缺省。

command

命令或者弥补规则操作的命令。有效命令是SELECT, INSERT, UPDATE, DELETE,或者NOTIFY. 组成规则动作的命令。有效的命令是SELECTINSERTUPDATEDELETENOTIFY语句之一。

conditioncommand里,特殊的表名字NEWOLD可以用于指向被引用表里的数值。 NEWON UPDATEON UPDATE规则里可以指向被插入或更新的新行。OLDON UPDATEON DELETE规则里可以指向现存的被更新或删除的行。 在conditioncommand中,特殊表名 NEWOLD可以用来指代所引用的 表中的值。NEWON INSERTON UPDATE规则 引用插入或更新新行是有效的, OLDON UPDATEON DELETE规则引用更新或删除现有行是有效的。

注意

为了在表上定义或修改规则,你必须是该表的拥有者。

在视图上用于INSERTUPDATEDELETE的规则中可以添加RETURNING子句基于视图的字段返回。 如果规则被INSERT RETURNINGUPDATE RETURNINGDELETE RETURNING命令触发,这些子句将用来计算输出结果。 如果规则被不带RETURNING的命令触发,那么规则的RETURNING子句将被忽略。目前仅允许无条件的 INSTEAD 规则包含 RETURNING 子句, 而且在同一个事件内的所有规则中最多只能有一个 RETURNING 子句。这样就确保只有一个RETURNING子句可以用于计算结果。 如果在任何有效规则中都不存在RETURNING子句,该视图上的RETURNING查询将被拒绝。

有一件很重要的事情是要避免循环规则。比如,尽管下面两条规则定义都是PostgreSQL可以接受的, 但其中的一条SELECT命令会导致PostgreSQL报告一条错误信息,因为该查询循环了太多次:

CREATE RULE "_RETURN" AS
    ON SELECT TO t1
    DO INSTEAD 
        SELECT * FROM t2;

CREATE RULE "_RETURN" AS
    ON SELECT TO t2
    DO INSTEAD 
        SELECT * FROM t1;

SELECT * FROM t1;

目前,如果一个规则包含一个NOTIFY命令,那么该NOTIFY命令将被无条件执行, 也就是说,即使规则不施加到任何行上面,该NOTIFY也会被执行。比如,在:

CREATE RULE notify_me AS ON UPDATE TO mytable DO ALSO NOTIFY mytable;

UPDATE mytable SET name = 'foo' WHERE id = 42;

里,一个NOTIFY事件将在UPDATE的时候发出, 不管是否有满足id = 42条件的行。 这是一个实现的限制,将来的版本应该修补这个毛病。

兼容性

CREATE RULEPostgreSQL语言的扩展, 整个规则重写系统都是如此。