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),而不是规则。
名称
要创建的规则的名称。该名称必须与同一表的任何其他规则的名称不同。对同一表和同一事件类型的多个规则将按照字母名称顺序应用。
事件
事件包括 SELECT
、INSERT
、UPDATE
或 DELETE
。请注意,包含 ON CONFLICT
子句的 INSERT
不能用于有 INSERT
或 UPDATE
规则的表。考虑改为使用可更新视图。
表名
应用规则的表或视图的名称(可选,限定模式)。
条件
任何SQL条件表达式(返回 boolean
)。条件表达式不能引用 NEW
和 OLD
之外的任何表,也不能包含聚合函数。
INSTEAD
INSTEAD
表示应 代替原始命令执行命令。
ALSO
ALSO
指 该命令应在原始命令之外执行。
如果未指定 ALSO
或 INSTEAD
,则缺省为 ALSO
。
命令
构成规则动作的命令。有效的命令有 SELECT
、INSERT
、UPDATE
、DELETE
或 NOTIFY
。
在 条件
和 命令
内,可以使用特殊表名 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;
其中一个 NOTIFY
事件将在 UPDATE
期间发送,而无论是否有任何行与条件 id = 42
匹配。这是一个实现限制,可能在未来的版本中得到修复。
CREATE RULE
是一个 PostgreSQL 语言扩展,整个查询重写系统也是如此。