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 语言扩展,整个查询重写系统也是如此。
如果您在文档中发现任何不正确的内容、与您对特定功能的体验不符的内容或需要进一步澄清的内容,请使用此表单报告文档问题。