选择 打开 改范围 完整检索页
受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10
当前 PostgreSQL 版本不在支持生命周期内。
您可以参阅当前版本的对应页面,或其他在上面列出的活跃大版本。

CREATE RULE

CREATE RULE — 定义一条新的重写规则

Synopsis

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 视图。必须认识到,规则实际上是一种命令转换机制,或者说 是命令宏。这种转换发生在命令开始执行之前。如果你真正需要的是对每个物理 行独立触发的操作,那么你很可能应该使用触发器,而不是规则。有关规则系统 的更多信息见Chapter 40

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

Note

足够简单、可自动更新的视图(见CREATE VIEW)不需要依靠用户创建的规则来实现更新。 虽然你仍然可以显式创建规则,但自动更新转换通常比显式规则性能更好。

另一种值得考虑的办法是使用INSTEAD OF触发器(见 CREATE TRIGGER)代替规则。

参数

name

要创建的规则的名称。它必须与同一个表上任何其他规则的名称相区分。 同一个表上同一种事件类型的多条规则会按名称的字母顺序应用。

event

事件是SELECTINSERTUPDATE或者 DELETE之一。注意,包含ON CONFLICT子句的INSERT 不能用于带有INSERTUPDATE规则的表。请考虑改用 可更新的视图。

table_name

规则适用的表或者视图的名称(可以是模式限定的)。

condition

任意的SQL条件表达式(返回 boolean)。条件表达式不能引用NEWOLD之外的任何表,并且不能包含聚合函数。

INSTEAD

INSTEAD表示这些命令应当 替代原始命令执行。

ALSO

ALSO表示这些命令应当在原始命令 之外执行。

如果既未指定ALSO,也未指定 INSTEAD,则默认值为ALSO

command

组成规则动作的命令。可用的命令有SELECTINSERTUPDATEDELETE或者NOTIFY

conditioncommand中,可以使用特殊表名 NEWOLD来引用目标表中的值。 在ON INSERTON UPDATE规则中, NEW可用于引用待插入或待更新的新行。在 ON UPDATEON DELETE规则中, OLD可用于引用将被更新或删除的现有行。

注解

要在表上创建或者修改规则,必须是表的拥有者。

在视图上的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;

UPDATE期间会发送一个NOTIFY事件, 无论是否存在匹配条件id = 42的行。这是一个实现限制, 未来版本中可能会修复。

兼容性

CREATE RULE是一种 PostgreSQL语言扩展, 整个查询重写系统也是如此。