Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

CREATE RULE

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

概要

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

where event can be one of:

    SELECT | INSERT | UPDATE | DELETE

说明

CREATE RULE 定义了一条应用于指定表或视图的新规则。 CREATE OR REPLACE RULE 要么会创建一个新规则,要么会用同名的新规则替换针对同一张表的现有规则。

PostgreSQL 规则系统允许定义对数据库表中的插入、更新或删除执行的备用操作。粗略来说,一条规则会导致在对给定表执行给定命令时执行其他命令。或者,INSTEAD 规则可以将给定命令替换为另一个命令,也可以导致根本不执行命令。规则用于实现 SQL 视图。重要的是要意识到规则实际上是一种命令转换机制,或命令宏。转换在命令执行开始前发生。如果你确实希望针对每一行物理数据独立触发操作,你可能想使用触发器,而不是规则。有关规则系统的更多信息,请参阅第 39 章

目前,ON SELECT 规则只能附加到视图。此类规则必须命名为"_RETURN",必须是无条件的 INSTEAD ,且必须有一个由单个 SELECT 命令组成的操作。此命令定义视图的可见内容。(视图本身基本上是没有任何存储的虚拟表。)最好将此类规则视为实施细节。虽然可以利用 CREATE OR REPLACE RULE "_RETURN" AS ... 重新定义视图,但是使用 CREATE OR REPLACE VIEW 更好。

你可以通过定义 ON INSERTON UPDATEON DELETE 来创造出可更新视图的假象(或足以满足你目的的任何规则子集),以用对其他表的适当更新替换视图上的更新操作。如果你希望支持 INSERT RETURNING 等,请务必在这些每个规则中放入适当的 RETURNING 子句。

如果您尝试将条件规则用于复杂的视图更新,需注意以下要点:对于您希望在视图上允许的每个操作,必须存在一个无条件的 INSTEAD 规则。如果规则有条件,或不是 INSTEAD,那么系统仍会拒绝执行更新操作的尝试,因为系统认为它最终可能尝试在某些情况下对视图的虚拟表执行操作。如果您想在条件规则中处理所有有用案例,请添加一个无条件的 DO INSTEAD NOTHING 规则,以确保系统理解永远不会对虚拟表进行更新。然后,将条件规则设置为非 INSTEAD;在应用了条件规则的场景中,它们将添加至默认 INSTEAD NOTHING 操作。(目前,此方法不支持 RETURNING 查询。)

注意

视图足够简单,可以自动更新(请参阅 CREATE VIEW),无需用户创建的规则即可进行更新。虽然您仍然可以创建显式规则,但自动更新转换通常会优于显式规则。

值得考虑的另一种替代方法是使用 INSTEAD OF 触发器(请参阅 CREATE TRIGGER),而不是规则。

参数

名称

要创建的规则的名称。该名称必须与同一表的任何其他规则的名称不同。对同一表和同一事件类型的多个规则将按照字母名称顺序应用。

事件

事件包括 SELECTINSERTUPDATEDELETE。请注意,包含 ON CONFLICT 子句的 INSERT 不能用于有 INSERTUPDATE 规则的表。考虑改为使用可更新视图。

表名

应用规则的表或视图的名称(可选,限定模式)。

条件

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

INSTEAD

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

ALSO

ALSO 指 该命令应在原始命令之外执行。

如果未指定 ALSOINSTEAD,则缺省为 ALSO

命令

构成规则动作的命令。有效的命令有 SELECTINSERTUPDATEDELETENOTIFY

条件命令 内,可以使用特殊表名 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 RULE 是一个 PostgreSQL 语言扩展,整个查询重写系统也是如此。

另请参见

ALTER RULEDROP RULE