pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
CREATE RULE — 定义一条新的重写规则
CREATE RULEnameAS ONeventTOobject[ WHEREcondition] DO [ INSTEAD ]actionwhereactioncan be: NOTHING |query| (query;query... ) | [query;query... ]
name要创建的规则的名称。
event事件是 SELECT、 UPDATE、DELETE 或 INSERT 之一。
objectObject 是 table 或 table.column。(目前,实际上只实现了 table 形式。)
condition任意的 SQL 布尔条件表达式。条件表达式不能 引用 new 和 old 之外的任何表。
query组成 action 的一个或多个查询 可以是任何 SQL 的 SELECT、INSERT、 UPDATE、DELETE 或 NOTIFY 语句。
在 condition 和 action 中,可以使用 特殊表名 new 和 old 来引用被引用表(即 object)中的值。 new 在 ON INSERT 和 ON UPDATE 规则中有效, 用于引用正在被插入或更新的新行。 old 在 ON UPDATE 和 ON DELETE 规则中有效,用于引用正在被更新或删除的现有行。
CREATE规则成功创建时返回的消息。
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 部分 与触发激活它的用户命令使用相同的命令标识符和事务标识符 执行。
目前,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 "_RETemp" AS
ON SELECT TO emp
DO INSTEAD
SELECT * FROM toyemp;
CREATE RULE "_RETtoyemp" 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 的行。这是一个实现限制, 未来版本中可能会修复。
CREATE RULE 语句是 PostgreSQL 的语言扩展。 SQL92 中没有 CREATE RULE 语句。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。