支持的版本:当前17)/ 16 / 15 / 14 / 13
开发版本:devel
不支持的版本:12 / 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 RULE, DROP RULE

提交更正

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