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;

更新规则

更新规则指的是针对 INSERT、UPDATE、DELETE 这 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,可使用 ALSO 或 INSTEAD
权限控制 规则从属于表/视图的所有者,用户只需显式权限
与触发器对比 规则更适合批量操作与查询重写,触发器更适合行级逻辑

相关推荐
zhangjw348 小时前
1-5 PostgreSQL 数据类型全集:基础类型、字符串、数值、时间类型
数据库·postgresql
odoo中国9 小时前
Odoo19 配置 PostgreSQL 数据库连接及故障排查
postgresql·odoo开发·数据库配置
考虑考虑12 小时前
瀚高数据库
数据库·后端·postgresql
IvorySQL14 小时前
开源数据库进校园| 11 月 3 日,IvorySQL 校园行走进浙大宁波校区:从 PostgreSQL 扩展生态到 AI 实战
数据库·postgresql·开源
瀚高PG实验室17 小时前
瀚高数据库创建新数据库卡住问题排查
数据库·postgresql·瀚高数据库
瀚高PG实验室1 天前
HGDB V9.0.5 .pgpass 免密登录提示 IsEncryptNon-base64 encoding 警告处理
数据库·postgresql·瀚高数据库
IvorySQL2 天前
PostgreSQL 日报|Anonymizer 3.3 修复高危漏洞(10 月 29 日)
数据库·postgresql
geovindu2 天前
SQL Data Sampling and Approximation Techniques using postgreSQL 18
大数据·数据库·数据仓库·sql·postgresql·数据库开发·数据库架构
小手cool2 天前
PostgreSQL 基础入门:从安装到核心概念
数据库·postgresql
代码派2 天前
PostgreSQL 同构迁移上云方案|NineData 数据复制、实时增量与一致性校验
数据库·postgresql·上云·ninedata·迁移·数据库迁移·版本升级