9.3 9.4 9.5 9.6 10 11
问题报告 纠错本页面

CREATE RULE

名称

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

大纲

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

这里的event可以是下列之一:

    SELECT | INSERT | UPDATE | DELETE

描述

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

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

目前,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查询。)

注意: 一个足够简单可以自动更新的视图(参阅CREATE VIEW) 不需要用户创建的使其可更新的规则。不过,你可以创建一个明确的规则, 自动更新转换通常比明确的规则执行的更好。

另一个可替换的价值考虑是使用INSTEAD OF触发器 (参阅CREATE TRIGGER)替代规则。

参数

name

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

event

SELECTINSERTUPDATEDELETE事件之一。

table_name

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

condition

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

INSTEAD

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

ALSO

ALSO指示该命令应该在最初的命令执行之后 一起执行。

如果既没有声明ALSO也没有声明INSTEAD, 那么ALSO是缺省。

command

组成规则动作的命令。有效的命令是SELECTINSERTUPDATEDELETENOTIFY语句之一。

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 语言的扩展,整个规则重写系统都是如此。

又见

ALTER RULE, DROP RULE