CREATE RULE — 定义一个新的重写规则
CREATE [ OR REPLACE ] RULEname
AS ONevent
TOtable_name
[ WHEREcondition
] DO [ ALSO | INSTEAD ] { NOTHING |command
| (command
;command
... ) } whereevent
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 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
任何SQL条件表达式(返回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 语言扩展,整个查询重写系统也是如此。
如果您发现文档中的任何内容不正确,与您使用特定功能的经验不符或需要进一步澄清,请使用此表单报告文档问题。