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 ... ) }

where event can be one of:

    SELECT | INSERT | UPDATE | DELETE

Description

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

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

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

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

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

Note

视图如果足够简单,可以自动更新(参见 CREATE VIEW ),则不需要用户创建的规则来实现可更新性。虽然你无论如何都可以创建显式规则,不过自动更新转换通常会优于显式规则。

另一个值得考虑的备选方案是用 INSTEAD OF 触发器(参见 CREATE TRIGGER )代替规则。

Parameters

  • name

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

  • event

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

  • table_name

    • 规则所应用的表或视图的名称(可选择限定架构)。

  • condition

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

  • INSTEAD

    • INSTEAD 表示应该 instead of 原始命令执行这些命令。

  • ALSO

    • ALSO 表示应该 in addition to 原始命令执行这些命令。

    • 如果没有指定 ALSOINSTEADALSO 是默认值。

  • command

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

conditioncommand 内,可以使用特殊表名 NEWOLD 引用被引用表中的值。 NEWON INSERTON UPDATE 规则中是有效的,用于引用要插入或更新的新行。 OLDON UPDATEON DELETE 规则中是有效的,用于引用要更新或删除的现有行。

Notes

你必须是表的拥有者才能创建或更改其规则。

在视图上的 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 匹配的行。这是一个将在未来版本中修复的实现限制。

Compatibility

CREATE RULE 是 PostgreSQL 语言扩展,就像整个查询重写系统一样。

See Also