大数跨境
0
0

PostgreSQL 18 - 时间约束(Temporal Constraints)实操指南

PostgreSQL 18 - 时间约束(Temporal Constraints)实操指南 IvorySQL开源数据库社区
2025-11-27
0
导读:以 UNIQUE 约束为示例

PostgreSQL 18 引入了一项强大的新功能,允许你在时间段内强制执行唯一性:时间约束(Temporal Constraints)。通过这一新增功能,你现在可以在定义 UNIQUEPRIMARY KEY 或 FOREIGN KEY 约束时,利用日期范围(Date Range)或时间戳范围(Timestamp Range)字段,比以往更容易地防止数据重叠。

问题所在:基于时间的唯一性

在最新的这个版本中,PostgreSQL 增加了一种更灵活的方式来定义 UNIQUEPRIMARY KEY 和 FOREIGN KEY 约束。我将把示例重点放在 UNIQUE 约束上,因为这在我看来是时间约束最有用的场景。

让我们从一个现实世界的场景开始:管理用户订阅。

设置示例

首先,我们有一个简单的 users 表,包含 2 行数据:

CREATE TABLEusers (
iduuidDEFAULT uuidv7() PRIMARY KEY,
  email VARCHAR(100UNIQUENOTNULL
);

INSERTINTOusers (email) VALUES
('darth@example.com'),
('luke@example.com');

使用 WITHOUT OVERLAPS 的时间约束

现在我想创建一个属于 users 表的 subscriptions(订阅)表。每个订阅都有开始和结束日期,我想确保每个用户的订阅是唯一的。用户可以有过去的订阅(也许他们升级了层级),但在任何给定的时间点只能有一个活跃的订阅。

以下是我们如何使用新的 WITHOUT OVERLAPS 语法来强制执行此操作:

CREATE TABLE subscriptions (
  user_id uuidNOTNULL,
typeVARCHAR(50NOTNULL,
  valid_period daterange NOTNULL,
FOREIGNKEY (user_id) REFERENCESusers(id),
UNIQUE (user_id, valid_period WITHOUT OVERLAPS)
);

如你所见,我们在 valid_period 这个 daterange 字段的 UNIQUE 约束中使用了 WITHOUT OVERLAPS。时间约束要求键列(valid_period)必须是范围类型(range type),因此通常你会使用 daterange 或 timestamprange,但它也适用于其他范围类型。

测试一下

让我们插入一些数据:

INSERT INTO subscriptions (user_id, type, valid_period)
SELECT u.id, 'basic', daterange('2024-01-01''2025-01-01''[)')
FROM users u;

INSERT INTO subscriptions (user_id, type, valid_period)
SELECT u.id, 'premium', daterange('2025-01-01''2026-01-01''[)')
FROM users u
WHERE u.email = 'darth@example.com';

SELECT * FROM subscriptions;

结果如下:

               user_id                |  type   |      valid_period
--------------------------------------+---------+-------------------------
 0199f293-291a-70bf-b9ee-872247723d29 | basic   | [2024-01-01,2025-01-01)
 0199f293-291b-737a-9bd0-e0e0853e3377 | basic   | [2024-01-01,2025-01-01)
 0199f293-291a-70bf-b9ee-872247723d29 | premium | [2025-01-01,2026-01-01)

在这个例子中,Luke 显然在 2025 年停止了付费,而 Darth 升级到了高级版。我通常习惯使用单独的列来表示开始和结束日期,但我很欣赏范围类型(Ranges)能够启用此功能,并允许我们使用强大的范围运算符。

额外内容:查询活跃订阅

使用“冰淇淋筒”运算符(@>,即包含运算符),我们可以轻松找到特定日期有效的订阅:

SELECT * FROM subscriptions
WHERE valid_period @> '2025-01-01'::date;

这个查询会告诉我们哪些订阅在 2025 年 1 月 1 日是活跃的。

重要提示:GIST 与 B-Tree 索引

有一个陷阱:范围列使用 GIST 索引,而 UUID 列使用 B-Tree 索引。当我运行 CREATE TABLE subscriptions 命令时,我遇到了一个错误。为了解决这个问题,你需要启用以下扩展:

CREATE EXTENSION btree_gist;

了解更多

如果你想深入了解时间约束,请查看 PostgreSQL 文档中关于 WITHOUT OVERLAPS[1] 的部分。

原文链接:https://hashrocket.com/blog/posts/postgresql-18-temporal-constraints

作者:Vinicius Negrisolo



IvorySQL 5.0 重磅发布,基于 PostgreSQL 18,欢迎使用。

详情见:IvorySQL 5.0 发布:基于 PG 18.0,Oracle 兼容、生态组件、云原生与易用性全面进化!

引用链接

[1] 

WITHOUT OVERLAPS: https://www.google.com/search?q=https://www.postgresql.org/docs/devel/ddl-constraints.html%23DDL-CONSTRAINTS-UNIQUE-WITHOUT-OVERLAPS

推荐阅读 -
活动预告|本周六!IvorySQL 邀您相聚第八届中国 PostgreSQL 数据库生态大会
IvorySQL 5.0 发布:基于 PG 18.0,Oracle 兼容、生态组件、云原生与易用性全面进化!
2025 开放原子开发者大会回顾|IvorySQL 内核实现原理
【开源之夏学生访谈】走进 IvorySQL:用一行命令,让数据库“跑”起来
沙中开源AI科技峰会2025成功举办:COPU与Parmg互聘顾问、成立DB SIG,中沙开源合作持续深入
一文读懂 PG18 EXPLAIN 新字段:Index Searches
- 关于 IvorySQL -
IvorySQL 是由瀚高股份主导研发的一款开源的兼容 Oracle 的 PostgreSQL。IvorySQL 与 PostgreSQL 国际社区紧密合作,保持与最新 PG 版本内核同步,为用户提供便捷的升级体验。基于双 Parser 架构设计,100% 与原生 PostgreSQL 兼容,支持丰富的 PostgreSQL 周边工具和扩展,并根据用户需求提供定制化工具。同时,IvorySQL 提供更全面灵活的 Oracle 兼容功能,具备高度的 SQL 和 PL/SQL 兼容性,能够为企业构建更加高效、稳定和灵活的数据库解决方案。
官网:https://www.ivorysql.org
GitHub( 欢迎点击 star 收藏 )https://github.com/IvorySQL/IvorySQL
社群微信搜索“ivorysql_official” 添加小助理进群
在线试用:http://trial.ivorysql.org:8080/


图片

【声明】内容源于网络
0
0
IvorySQL开源数据库社区
IvorySQL 是由瀚高开发,基于 PostgreSQL 的一款具备强大 Oracle 兼容能力的开源数据库。紧跟 PG 社区,快速进行版本迭代,保持与最新版本 PG 数据库内核同步,并支持丰富的 PG 周边工具和扩展。
内容 278
粉丝 0
IvorySQL开源数据库社区 IvorySQL 是由瀚高开发,基于 PostgreSQL 的一款具备强大 Oracle 兼容能力的开源数据库。紧跟 PG 社区,快速进行版本迭代,保持与最新版本 PG 数据库内核同步,并支持丰富的 PG 周边工具和扩展。
总阅读29
粉丝0
内容278