由 John Doe 四月 3, 2026
PostgreSQL 已经开始支持时态数据部分更新与删除的能力,彻底填补应用时间维度区间数据操作的原生语法空白,大幅简化了范围型时态数据的修改逻辑。

特性提交日志
新增 UPDATE/DELETE FOR PORTION OF 语法。
本功能是对 UPDATE 与 DELETE 命令的扩展,用于基于范围(range)或多范围(multirange)列执行 “时态更新 / 时态删除” 操作。用户可以编写如下语句:
UPDATE t FOR PORTION OF valid_at FROM '2001-01-01' TO '2002-01-01' SET ...
(DELETE 语句用法类似),其中 valid_at 为范围或多范围类型列。
该命令会自动限定仅作用于与目标时段重叠的数据行,且仅修改该时段范围内的历史记录。如果某一行对应的历史记录部分落在目标时段内、部分落在时段外,命令会先将该行的应用时间截断至目标时段范围内,然后插入一条或多条 “时态剩余记录”:新行保留原行所有字段值,仅修改应用时间列,使其仅代表未被修改的历史部分。
为计算所需的时态剩余记录,本功能使用了在之前提交中定义的 *_minus_multi 集合返回函数。
- 为 FOR PORTION OF 语法增加了 Bison 解析支持。边界值必须为常量,因此禁止使用列引用、子查询等写法;但允许使用
NOW()这类函数。 - 在执行器中新增逻辑,用于为被 FOR PORTION OF 语句命中的记录插入代表 “时态剩余部分” 的新行。
- 完成 FOR PORTION OF 语法的文档编写。
- 添加了相应测试用例。
讨论:https://www.postgresql.org/message-id/flat/ec498c3d-5f2b-48ec-b989-5561c8aa2024%40illuminatedcomputing.com
特性示例
在人力资源管理领域,存在员工薪资周期调整的应用场景,用于管理员工薪资、职级、任职状态的生效周期,实现历史可追溯、未来可预设。
创建表结构,插入测试数据:
CREATE TABLE employee_salary (
emp_id INT,
emp_name TEXT,
salary NUMERIC(10,2),
valid_at daterange,
PRIMARY KEY (emp_id, valid_at)
);
-- 插入员工2024-2026年的薪资记录
INSERT INTO employee_salary VALUES
(1001, '张三', 15000, '[2024-01-01, 2026-01-01)');
调整员工张三 2025 年全年的薪资为 18000,保留 2024 年的薪资记录不变,无需手动拆分数据。
UPDATE employee_salary
FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
SET salary = 18000
WHERE emp_id = 1001;
执行完成后,数据库自动拆分原行,最终生成两条无重叠、无断层的记录:
| emp_id | emp_name | salary | valid_at |
|---|---|---|---|
| 1001 | 张三 | 15000.00 | [2024-01-01, 2025-01-01) |
| 1001 | 张三 | 18000.00 | [2025-01-01, 2026-01-01) |
非常不错的体验,感谢所有参与的社区人员。
参考
提交日志:https://git.postgresql.org/pg/commitdiff/8e72d914c52876525a90b28444453de8085c866f