2024年9月26日: PostgreSQL 17 发布!
支持版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

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)代替规则。

参数

name

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

event

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

table_name

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

condition

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

INSTEAD

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

ALSO

ALSO 表示应除了原始命令之外执行这些命令。

如果没有指定 ALSOINSTEAD,则默认值为 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;

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

兼容性

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

另请参阅

ALTER RULEDROP RULE

提交更正

如果您在文档中发现任何不正确的内容、与您对特定功能的体验不符的内容或需要进一步澄清的内容,请使用此表单报告文档问题。