CREATE RULE — 定义一个新的重写规则
CREATE [ OR REPLACE ] RULEnameAS ONeventTOtable_name[ WHEREcondition] DO [ ALSO | INSTEAD ] { NOTHING |command| (command;command... ) } whereeventcan 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,并且不能包含聚合函数。
INSTEADINSTEAD表示应该代替原始命令执行这些命令。
ALSOALSO表示应该除了原始命令之外还执行这些命令。
如果未指定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 语言扩展,整个查询重写系统也是如此。
如果您发现文档中的任何内容不正确,与您使用特定功能的经验不符或需要进一步澄清,请使用此表单报告文档问题。