尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

PostgreSQL 18 - 时间约束 (Temporal Constraints)

PostgreSQL 18 - 时间约束 (Temporal Constraints)
📅 发布时间:2026/6/19 12:02:17

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

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

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

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

设置示例

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

CREATE TABLE users (id uuid DEFAULT uuidv7() PRIMARY KEY,email VARCHAR(100) UNIQUE NOT NULL
);INSERT INTO users (email) VALUES 
('darth@example.com'),
('luke@example.com');

使用 WITHOUT OVERLAPS 的时间约束

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

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

CREATE TABLE subscriptions (user_id uuid NOT NULL,type VARCHAR(50) NOT NULL,valid_period daterange NOT NULL,FOREIGN KEY (user_id) REFERENCES users(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 的部分。

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

作者:Vinicius Negrisolo

相关新闻

  • 升级Win11专业工作站版密钥
  • 多线程+asyncio端口扫描器
  • U635735 Treap=Tree+Heap

最新新闻

  • RTXGI-DDGI入门指南:如何快速掌握NVIDIA实时全局光照技术
  • (2026新)百色正规防水补漏公司口碑榜TOP5权威推荐!卫生间/厨房/阳台/屋顶/天花板/地下室渗漏水检测维修攻略-靠谱漏水检测维修师傅推荐 - 安佳防水
  • AspectMock与Codeception完美结合:构建全面的PHP测试套件
  • Presenton开源AI演示生成工具:企业级演示文稿创作的完整解决方案
  • Awesome-AI 开源仓库架构设计与技术学习路线工程化沉淀方案
  • (2026新)珠海正规防水补漏公司口碑榜TOP5权威推荐!卫生间/厨房/阳台/屋顶/天花板/地下室渗漏水检测维修攻略-靠谱漏水检测维修师傅推荐 - 安佳防水

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号