PostgreSQL 规则简介 - 创建不可修改的条目

来自 PostgreSQL Wiki
跳转到导航跳转到搜索

作者:Justin Clift

简介

你试过 PostgreSQL 的“规则”吗?如果你还没有,你可能会喜欢这个快速实用的介绍,你可能会马上用上它!

PostgreSQL 规则用于在查询执行之前拦截和更改查询。例如,假设你有一个表格,人们可以在其中添加内容,但你需要在表格中添加 3 个永远不能修改或删除的条目。这就是你该怎么做。

让我们创建一个示例表格

foo=> CREATE TABLE gift_certificates (idnum serial, person varchar(20), amount float4);
NOTICE: CREATE TABLE will create implicit sequence 'gift_certificates_idnum_seq' for SERIAL column 'gift_certificates.idnum'
NOTICE: CREATE TABLE/UNIQUE will create implicit index 'gift_certificates_idnum_key' for table 'gift_certificates'
CREATE

让我们给它一些数据

foo=> insert into gift_certificates (person, amount) values ('Justin', 200);
INSERT 51564057 1
foo=> insert into gift_certificates (person, amount) values ('Tom', 200);
INSERT 51564059 1
foo=> insert into gift_certificates (person, amount) values ('Richard', 200);
INSERT 51564062 1
foo=> insert into gift_certificates (person, amount) values ('Peter', 200);
INSERT 51564065 1
foo=> insert into gift_certificates (person, amount) values ('Bruce', 200);
INSERT 51564066 1
foo=> insert into gift_certificates (person, amount) values ('Marc', 200);
INSERT 51564067 1
foo=> insert into gift_certificates (person, amount) values ('Vince', 200);

foo=> select * from gift_certificates;
 idnum |  person | amount
-------+---------+--------
     1 | Justin  | 200
     2 | Tom     | 200
     3 | Richard | 200
     4 | Peter   | 200
     5 | Bruce   | 200
     6 | Marc    | 200
     7 | Vince   | 200
(7 rows)

在这个例子中,你将创建两个规则

foo=> CREATE RULE prot_gc_upd AS ON UPDATE TO gift_certificates WHERE old.idnum < 4 DO INSTEAD nothing;
CREATE
foo=> CREATE RULE prot_gc_del AS ON DELETE TO gift_certificates WHERE old.idnum < 4 DO INSTEAD nothing;
CREATE

“nothing” 子句是合法的 PostgreSQL 规则子句,它有效地删除了 SQL 查询会更新 gift_certificates 表中前 3 个条目中的任何一个的操作。不过,在该表上运行的所有 SQL 查询都将完美运行(除了那些试图更新或删除前 3 个条目中的任何一个的查询)。

出于兴趣,WHERE 子句可以是任何标准的 SQL WHERE 子句。这个例子还添加了 “old” 关键字到 idnum 字段。 “old.idnum” 字段的意思是“在尝试查询开始之前存在的 idnum 版本”。阅读手册了解更多信息。:)

现在,让我们测试一下

foo=> update gift_certificates set person = 'Justin2' where idnum = 1;
UPDATE 0
foo=> update gift_certificates set person = 'Justin2' where idnum = 2;
UPDATE 0
foo=> update gift_certificates set person = 'Justin2' where idnum = 3;
UPDATE 0
foo=> update gift_certificates set person = 'Justin2' where idnum = 4;
UPDATE 1

看看最后一次更新是如何工作的,因为它没有受到 PostgreSQL 规则的保护?

foo=> select * from gift_certificates;
 idnum |  person | amount
-------+---------+--------
     1 | Justin  | 200
     2 | Tom     | 200
     3 | Richard | 200
     5 | Bruce   | 200
     6 | Marc    | 200
     7 | Vince   | 200
     4 | Justin2 | 200
(7 rows)

foo=>

上面的删除规则也起作用了

foo=> delete from gift_certificates;
DELETE 4
foo=> select * from gift_certificates;
 idnum |  person | amount
-------+---------+--------
     1 | Justin  | 200
     2 | Tom     | 200
     3 | Richard | 200
(3 rows)

foo=>

很酷吧?

希望你发现它有用!

有关 PostgreSQL 规则的更多信息,请参考 PostgreSQL 程序员指南,“"PostgreSQL 规则系统"”。