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 视图。重要的是要认识到规则实际上是一种命令转换机制或命令宏。转换在命令执行开始之前发生。如果您实际需要一个针对每行物理行独立触发的操作,则可能希望使用触发器,而不是规则。有关规则系统的更多信息,请参阅第 41 章。
目前,ON SELECT
规则只能附加到视图。此类规则必须命名为"_RETURN"
,必须是无条件的INSTEAD
规则,并且必须包含由单个SELECT
命令组成的操作。此命令定义视图的可见内容。(视图本身基本上是一个没有存储的虚拟表。)最好将此类规则视为实现细节。虽然可以通过CREATE OR REPLACE RULE "_RETURN" AS ...
重新定义视图,但最好使用CREATE OR REPLACE VIEW
。
您可以通过定义ON INSERT
、ON UPDATE
和ON DELETE
规则(或足以满足您目的的任何子集)来创建可更新视图的假象,以用其他表上的适当更新替换视图上的更新操作。如果您想支持INSERT RETURNING
等,那么请务必在每个规则中放入一个合适的RETURNING
子句。
如果您尝试对复杂视图更新使用条件规则,则有一个问题:必须为希望在视图上允许的每个操作提供一个无条件的INSTEAD
规则。如果规则有条件,或不是INSTEAD
,则系统仍会拒绝执行更新操作的尝试,因为它认为在某些情况下它可能最终尝试对视图的虚拟表执行操作。如果您想在条件规则中处理所有有用的情况,请添加一个无条件的DO INSTEAD NOTHING
规则,以确保系统理解它永远不会被调用来更新虚拟表。然后使条件规则变为非INSTEAD
;在应用它们的情况下,它们会添加到默认INSTEAD NOTHING
操作。(但是,此方法目前无法用于支持RETURNING
查询。)
注意
一个足够简单的视图可以自动更新(参见CREATE VIEW),不需要用户创建的规则即可更新。虽然无论如何都可以创建一个显式规则,但自动更新转换通常会优于显式规则。另一个值得考虑的替代方案是使用INSTEAD OF
触发器(参见CREATE TRIGGER),而不是规则。
参数
name
要创建的规则的名称。这必须不同于同一表的任何其他规则的名称。同一表和同一事件类型的多个规则按字母顺序应用名称。
event
事件之一
SELECT
、INSERT
、UPDATE
或DELETE
。请注意,包含ON CONFLICT
子句的INSERT
不能用于具有INSERT
或UPDATE
规则的表。考虑改用可更新视图。table_name
应用规则的表或视图的名称(可选地限定架构)。
condition
任何 条件表达式(返回
boolean
)。条件表达式不能引用NEW
和OLD
之外的任何表,并且不能包含聚合函数。INSTEAD
INSTEAD
表示应执行命令 而不是 原始命令。ALSO
ALSO
表示应执行命令 除了 原始命令。如果未指定
ALSO
或INSTEAD
,则ALSO
为默认值。command
构成规则操作的命令或命令。有效命令为
SELECT
、INSERT
、UPDATE
、DELETE
或NOTIFY
。
在*condition
和command
*中,可以使用特殊表名NEW
和OLD
来引用被引用表中的值。NEW
在ON INSERT
和ON UPDATE
规则中有效,用于引用正在插入或更新的新行。OLD
在ON UPDATE
和ON DELETE
规则中有效,用于引用正在更新或删除的现有行。
注释
您必须是表格的所有者才能创建或更改其规则。
在视图上的INSERT
、UPDATE
或DELETE
规则中,您可以添加RETURNING
子句,以发出视图的列。如果规则由INSERT RETURNING
、UPDATE RETURNING
或DELETE 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语言扩展,整个查询重写系统也是如此。