由 John Doe 十一月 4, 2025
你是否需要在表中跟踪行随时间的变化?PostgreSQL 18 的时态性主键就可以做到这一点。

特性提交日志
添加时态性的主键和唯一约束。
在主键和唯一约束中添加WITHOUT OVERLAPS子句。这是由 GiST 索引而不是 B 树索引提供支持,因为它们本质上是排除性约束,对于键的标量部分使用=,对于时态部分使用&&。
因为'empty' && 'empty'为假,所以时态性主键/唯一约束允许重复,这会让用户感到困惑,也不符合内部预期。例如,当GROUP BY检查主键上的函数依赖时,它允许从表中选择其他列,但在存在重复键的情况下,你可能会从任意一行获取值。所以我们需要禁止空值。
这意味着目前对于时态性主键/唯一约束,我们仅支持 range 和 multirange 类型。相关的文档和测试已添加。未来,通过为其他类型引入对更通用的 “空值” 概念的支持,这一功能还可以得到扩展。
示例
首先,我们快速定义一下时态数据库:这类数据库会追踪随时间变化的数据。与仅存储信息最新状态不同,时态数据库不仅记录数据“是什么”,还会记录数据在其生命周期内“曾经是什么”的历史信息。
PostgreSQL 18 对时态数据库的支持进行了优化,为主键和唯一约束新增了WITHOUT OVERLAPS子句。这一改进使 PostgreSQL 更接近完整的时态数据库能力,它强制实施了时态数据的核心规则:对于相同的业务键,其有效的时间区间不得重叠。
下面是将 PostgreSQL 用作时态数据库的一个简单示例:
-- 加载该扩展,以支持索引正常工作
CREATE EXTENSION btree_gist;
CREATE TABLE bookings (
room_id int NOT NULL, -- 房间ID
during tstzrange NOT NULL, -- 预订时间段(带时区的时间范围类型)
-- 时态主键:最后一列使用 WITHOUT OVERLAPS 子句
PRIMARY KEY (room_id, during WITHOUT OVERLAPS)
);
上述主键约束可确保:同一房间在任意时间点都不会出现重复预订(即预订时间段不重叠)。
此外,外键约束现在可通过PERIOD关键字关联时间区间,该功能支持范围类型(range)和多范围类型(multirange)。时态性外键不再通过“等值比较”验证,而是通过“范围包含关系”来进行校验。
确实很棒,非常感谢所有参与其中的相关人员。
参考
提交日志:https://git.postgresql.org/pg/commitdiff/fc0438b4e80535419a4e54dba87642cdf84defda