PostgreSQL 19: 支持 UPDATE/DELETE FOR PORTION OF 语法

John Doe 四月 3, 2026

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

image

特性提交日志

新增 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