2-6.pg特性功能之系列规则介绍和使用

PostgreSQL 规则系统介绍与使用

什么叫规则?

规则系统,更准确地说是查询重写规则系统,是 PostgreSQL 中一种在 SQL 命令执行前根据内部规则定义将其改写为另一个 SQL 命令的机制。


SELECT 规则

PostgreSQL 的视图是通过 SELECT 规则实现的。视图本质上是一个 SELECT 规则。

示例

sql 复制代码
-- 创建表
CREATE TABLE t (id INT, name VARCHAR);

-- 创建视图
CREATE VIEW myview AS SELECT * FROM t;

等价于:

sql 复制代码
CREATE TABLE myview (same column list as t);
CREATE RULE "_RETURN" AS
    ON SELECT TO myview
    DO INSTEAD SELECT * FROM t;

使用 \dt\dv 查看表和视图,会发现视图实际上是一张表,并在其上附加了一个 SELECT 规则。

SELECT 规则的限制

  1. 后续动作只能是 INSTEAD
  2. 规则的名称只能是 "_RETURN"
  3. 只能创建在空表上。
错误示例
sql 复制代码
CREATE TABLE mytab1(id INT, note VARCHAR(40));
CREATE TABLE mytab2(id INT, note VARCHAR(40));

-- 错误1:SELECT 规则必须使用 INSTEAD
CREATE RULE myrule AS ON SELECT TO mytab2 DO ALSO SELECT * FROM mytab1;

-- 错误2:规则名称必须为 "_RETURN"
CREATE RULE myrule AS ON SELECT TO mytab2 DO INSTEAD SELECT * FROM mytab1;

-- 正确:将 mytab2 变为一个视图
CREATE RULE "_RETURN" AS ON SELECT TO mytab2 DO INSTEAD SELECT * FROM mytab1;

更新规则

更新规则指的是针对 INSERTUPDATEDELETE 这 3 种 DML 操作的规则。

动作类型:ALSO 与 INSTEAD

  • ALSO:执行原操作后,额外执行规则中的动作。
  • INSTEAD:不执行原操作,只执行规则中的动作。

示例1:创建 INSERT 规则禁止插入数据

sql 复制代码
CREATE TABLE t (id INT, name VARCHAR);
INSERT INTO t VALUES (1, 'aaa'), (2, 'aaadd');

-- 创建规则:执行 INSERT 时什么都不做
CREATE RULE t_r AS ON INSERT TO t DO INSTEAD NOTHING;

-- 尝试插入,不会插入数据
INSERT INTO t VALUES (7, 'cha');

示例2:记录表的所有 DML 操作

sql 复制代码
-- 创建主表
CREATE TABLE mytab (
    id INT PRIMARY KEY,
    note TEXT
);

-- 创建操作记录表
CREATE TABLE mytab_log (
    seq BIGSERIAL PRIMARY KEY,
    oprtype CHAR(1),
    oprtime TIMESTAMP,
    old_id INT,
    new_id INT,
    old_note TEXT,
    new_note TEXT
);

-- 创建 INSERT 规则
CREATE RULE rule_mytab_insert AS
    ON INSERT TO mytab
    DO ALSO
        INSERT INTO mytab_log (oprtype, oprtime, new_id, new_note)
        VALUES ('i', NOW(), NEW.id, NEW.note);

-- 创建 UPDATE 规则
CREATE RULE rule_mytab_update AS
    ON UPDATE TO mytab
    DO ALSO
        INSERT INTO mytab_log (oprtype, oprtime, old_id, new_id, old_note, new_note)
        VALUES ('u', NOW(), OLD.id, NEW.id, OLD.note, NEW.note);

-- 创建 DELETE 规则
CREATE RULE rule_mytab_delete AS
    ON DELETE TO mytab
    DO ALSO
        INSERT INTO mytab_log (oprtype, oprtime, old_id, old_note)
        VALUES ('d', NOW(), OLD.id, OLD.note);

对原表操作

sql 复制代码
INSERT INTO mytab VALUES (1, 'note1');
UPDATE mytab SET note = 'updated' WHERE id = 1;
DELETE FROM mytab WHERE id = 1;

每条操作都会在 mytab_log 中留下记录。


规则与权限

规则从属于表或视图。如果一张表属于某个用户,则该表上的所有规则都属于该用户。用户只需要对查询中明确指定的表拥有所需权限即可进行操作。

示例

sql 复制代码
-- 用户 osdba 创建视图
CREATE VIEW myview AS SELECT id FROM mytab;
GRANT SELECT ON myview TO user01;

如果用户 user01 对底层表 mytab 没有权限,但拥有视图 myview 的查询权限,则仍可通过视图访问数据。


修改规则

sql 复制代码
ALTER RULE name ON table_name RENAME TO new_name;
  • name:现有规则的名称。
  • table_name:规则所属的表或视图(可模式限定)。
  • new_name:规则的新名称。

删除规则

sql 复制代码
DROP RULE t_rule ON t;

规则与触发器的比较

特性 规则 触发器
实现方式 查询重写 逐行触发
适用场景 批量操作、查询改写 行级操作、复杂逻辑
概念复杂度 较高 较低
性能影响 可能生成更优计划 逐行处理可能较慢

何时使用规则?何时使用触发器?

  • 规则:适用于批量操作或需要查询重写的场景,可能生成更好的执行计划,效率更高。
  • 触发器:适用于逐行处理的复杂逻辑,概念简单,易于理解和维护。

总结

功能 说明
SELECT 规则 用于实现视图,必须命名为 _RETURN,只能使用 INSTEAD
更新规则 支持 INSERT/UPDATE/DELETE,可使用 ALSOINSTEAD
权限控制 规则从属于表/视图的所有者,用户只需显式权限
与触发器对比 规则更适合批量操作与查询重写,触发器更适合行级逻辑

相关推荐
NotFound48611 小时前
分享实战心得PostgreSQL 主从复制:告别单点故障,附主从切换与延迟监控命令
数据库·postgresql
Pluto_CSND18 小时前
PostgreSQL 聚合函数总览
数据库·postgresql
石工记1 天前
postgresql18 安装-运行
数据库·postgresql
csdn2015_1 天前
postgresql string_to_array 方法
数据库·postgresql
编程经验分享1 天前
Windows 安装 PostgreSQL 并安装 vector 扩展
数据库·postgresql
韩楚风1 天前
PostgreSQL入门与进阶学习,体系化的SQL知识,完成终极目标高可用与容灾,性能优化与架构设计,以及安全策略
sql·学习·postgresql
Edward Nygma2 天前
zyy~P0 【OKR】智能解读组件专项-看板解读接算法
postgresql
Edward Nygma2 天前
zyy~P0 潜客探查专项-潜客探查优化
postgresql
源来猿往2 天前
mysql转postgresql【平移】
数据库·mysql·postgresql