↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本。 PostgreSQL 7.3 已结束支持。 请参阅 当前版本手册.

CREATE RULE

CREATE RULE — 定义一条新的重写规则

大纲

CREATE [ OR REPLACE ] RULE name AS ON event
    TO table [ WHERE condition ]
    DO [ INSTEAD ] action

where action can be:

NOTHING
| query
| ( query ; query ... )
  

输入

name

要创建的规则的名称。它必须与同一个表上任何其他规则的名称相区分。

event

事件是 SELECT、UPDATE、DELETE 或 INSERT 之一。

table

规则适用的表或视图的名称(可以是模式限定的)。

condition

任意的 SQL 条件表达式(返回 boolean)。条件表达式不能引用 new 和 old 之外的任何表,并且不能包含聚合函数。

query

组成 action 的一个或多个查询可以是任何 SQL 的 SELECT、INSERT、UPDATE、DELETE 或 NOTIFY 语句。

在 condition 和 action 中,可以使用特殊表名 new 和 old 来引用被引用表中的值。new 在 ON INSERT 和 ON UPDATE 规则中有效,用于引用正在被插入或更新的新行。old 在 ON UPDATE 和 ON DELETE 规则中有效,用于引用正在被更新或删除的现有行。

输出

CREATE RULE

规则成功创建时返回的消息。

描述

CREATE RULE 为一个指定的表或视图定义一条新的规则。CREATE OR REPLACE RULE 要么创建一条新规则,要么替换同一个表上同名的现有规则。

PostgreSQL 的规则系统允许定义在对数据库表进行插入、更新或删除时所执行的替代动作。规则也用于实现表视图。

一条规则的语义是:当单个实例(行)被访问、插入、更新或删除时,会有一个旧实例(对于选择、更新和删除)和一个新实例(对于插入和更新)。给定事件类型和给定目标表的所有规则会被依次(按名称顺序)检查。如果 WHERE 子句中指定的 condition(如果有)为真,该规则的 action 部分就会被执行。如果指定了 INSTEAD,action 会替代原始查询执行;否则,对于 ON INSERT,它在原始查询之后执行,而对于 ON UPDATE 或 ON DELETE,它在原始查询之前执行。在 condition 和 action 两部分中,旧实例和/或新实例中字段的值会替换到 old.attribute-name 和 new.attribute-name 上。

规则的 action 部分可以由一个或多个查询组成。要编写多个查询,需用圆括号包围它们。这些查询会按指定的顺序执行。action 也可以是 NOTHING,表示没有任何动作。因此,一条 DO INSTEAD NOTHING 规则会阻止原始查询的执行(当其条件为真时);而一条 DO NOTHING 规则没有任何用处。

规则的 action 部分与触发激活它的用户命令使用相同的命令标识符和事务标识符执行。

必须认识到,规则实际上是一种查询转换机制,或者说查询宏。整个查询会被处理并转换为一系列包含规则动作的查询。这发生在查询开始求值之前。因此,有条件的规则是通过把规则条件加到由该规则导出的动作的 WHERE 子句中来处理的。上面把规则描述为对每一行执行的操作因而有一定的误导性。如果你真正需要的是对每个物理行独立触发的操作,那么你很可能应该使用触发器而不是规则。规则最适合那些需要独立于所处理的具体数据来转换整个查询的场合。

规则与视图

目前,ON SELECT 规则必须是无条件的 INSTEAD 规则,并且其动作必须由单个 SELECT 查询组成。因此,一条 ON SELECT 规则实际上会把表变为视图,其可见内容是该规则的 SELECT 查询返回的行,而不是表中原来存储的内容(如果有)。直接编写 CREATE VIEW 命令被认为比创建真实表并为其定义 ON SELECT 规则的风格更好。

CREATE VIEW会创建一个虚拟表(没有底层存储)并为其关联一条 ON SELECT 规则。系统不会允许对该视图的更新,因为它知道那里没有真实的表。你可以通过定义 ON INSERT、ON UPDATE 和 ON DELETE 规则(或其中足以满足你需求的任意子集),将视图上的更新动作替换为对其他表的适当更新,从而营造出可更新视图的效果。

如果你尝试对视图更新使用有条件规则,这里有一个陷阱:对于你希望允许在该视图上执行的每一种动作,必须都有一条无条件的 INSTEAD 规则。如果该规则是有条件的,或者不是 INSTEAD,那么系统仍会拒绝执行该更新动作的尝试,因为它认为在某些情况下最终可能还是会尝试在该虚拟表上执行该动作。如果你想用有条件规则处理所有有用的情况,可以;只需加上一条无条件的 DO INSTEAD NOTHING 规则,以确保系统明白它永远不会被要求去更新这个虚拟表。然后把这些有条件规则改为非 INSTEAD;在它们触发的情况下,它们会附加在默认的 INSTEAD NOTHING 动作之上。

注解

要在一个表上定义规则,你必须拥有该表的规则定义权限。使用 GRANT 和 REVOKE 来更改权限。

避免循环规则非常重要。例如,尽管下面两条规则定义中的每一条都被 PostgreSQL 接受,但 select 命令会导致 PostgreSQL 报告错误,因为查询循环了太多次:

CREATE RULE "_RETURN" AS
    ON SELECT TO emp
    DO INSTEAD 
	SELECT * FROM toyemp;

CREATE RULE "_RETURN" AS
    ON SELECT TO toyemp
    DO INSTEAD 
	SELECT * FROM emp;

这个从 EMP 中选择的尝试会导致 PostgreSQL 报错,因为这些查询循环了太多次:

SELECT * FROM emp;

当前,如果一个规则包含一个 NOTIFY 查询,该 NOTIFY 会被无条件执行 —— 也就是说,即使没有任何应当应用该规则的行,也会发出 NOTIFY。例如,在

CREATE RULE notify_me AS ON UPDATE TO mytable DO NOTIFY mytable;

UPDATE mytable SET name = 'foo' WHERE id = 42;
      

中,在 UPDATE 期间会发送一个 NOTIFY 事件,无论是否存在 id = 42 的行。这是一个实现限制,未来版本中可能会修复。

兼容性

SQL92

CREATE RULE 是 PostgreSQL 的语言扩展。SQL92 中没有 CREATE RULE 语句。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.