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

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

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 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 已于 2007 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

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 语句。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。