↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

百科 / SQL 命令 / 触发器与规则

SQL COMMAND · 触发器与规则

CREATE RULE

定义一条新的重写规则

CREATE触发器与规则引入 10(基线)现存至 20 devel0 次语法变更

动词
CREATE
对象
RULE
引入版本
10(基线)
状态
现存
语法变更次数
0
手册小节数
5

本站手册 · 18官方文档 ↗

版本轨迹

相对 PostgreSQL 17 无变化。

语法铁道图 PostgreSQL 18

沿轨道从左向右阅读,分岔表示选择,绕行表示可选,回环表示重复。方框为参数,点击带下划线的参数可展开子规则。

CREATE OR REPLACE RULE name AS ON event TO table_name WHERE condition DO ALSO INSTEAD NOTHING command ( command ; command )
event
SELECT INSERT UPDATE DELETE

语法概要

CREATE [ OR REPLACE ] RULE name AS ON event
    TO table_name [ WHERE condition ]
    DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }

其中 event 可以是以下之一:

    SELECT | INSERT | UPDATE | DELETE

PostgreSQL 18 手册 · 查看完整参考页

描述

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来引用目标表中的值。在ON INSERT和ON UPDATE规则中,NEW可用于引用待插入或待更新的新行。在 ON UPDATE和ON DELETE规则中,OLD可用于引用将被更新或删除的现有行。

注解

要在表上创建或者修改规则,必须是表的拥有者。

在视图上的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语言扩展,整个查询重写系统也是如此。

另见

语法演化

相邻大版本之间的差异,新的在前。版本号链接到对应快照。

  1. PostgreSQL 17← 16正文更新

    正文更新
  2. PostgreSQL 16← 15正文更新

    正文更新
  3. PostgreSQL 14← 13正文更新

    正文更新
  4. PostgreSQL 12← 11正文更新

    正文更新
  5. PostgreSQL 11← 10正文更新

    正文更新

同组命令

命令动词对象版本变动最近变更
TRIGGERS & RULES触发器与规则9 条↑
CREATE EVENT TRIGGERCREATEEVENT TRIGGER 111 次
定义一个新的事件触发器现存
ALTER EVENT TRIGGERALTEREVENT TRIGGER 141 次
更改事件触发器的定义现存
DROP EVENT TRIGGERDROPEVENT TRIGGER —
移除一个事件触发器现存
CREATE RULECREATERULE —
定义一条新的重写规则现存
ALTER RULEALTERRULE —
修改一条重写规则的定义现存
DROP RULEDROPRULE —
移除一条重写规则现存
CREATE TRIGGERCREATETRIGGER 193 次
定义一个新触发器现存
ALTER TRIGGERALTERTRIGGER 131 次
更改触发器的定义现存
DROP TRIGGERDROPTRIGGER —
移除一个触发器现存