内容提要
Postgres 19新增三项实用语法:ON CONFLICT DO SELECT实现“获取或创建”,返回现有行并支持行锁;GROUP BY ALL自动分组非聚合列,简化查询;COPY支持JSON格式输出,可生成合法JSON文档。这些改进减少样板代码,提升日常开发效率。
延伸解读
ON CONFLICT DO SELECT 的实际价值
在 Postgres 19 之前,实现“获取或创建”通常需要借助 DO UPDATE 进行无操作更新,这会导致不必要的写入和表膨胀。DO SELECT 直接返回现有行,避免了这种浪费。此外,它支持行级锁(如 FOR UPDATE),可在并发场景下保护返回的行,确保事务一致性。这一特性对需要原子性“获取或创建”操作的应用程序尤为实用。
GROUP BY ALL 的便利与潜在风险
GROUP BY ALL 自动分组所有非聚合列,简化了查询编写,尤其当 SELECT 列表频繁变动时,可减少因漏写分组列而导致的语法错误。但需注意,它可能使查询结果意外增加列,影响依赖列位置的下游处理(如无表头的 CSV 解析)。因此,在现有报告或管道中引入该特性时,应通过测试确保输出符合预期。
COPY 输出 JSON 的适用场景与限制
COPY 新增的 JSON 格式支持直接输出合法 JSON,包括嵌套数组和 jsonb 对象,无需额外处理。FORCE_ARRAY 选项可生成完整的 JSON 数组,便于整体解析。但该功能仅支持 COPY TO,不支持 COPY FROM,且不能与 CSV 格式选项混用。对于需要将查询结果导出为 JSON 文件供下游工具使用的场景,这一特性显著简化了流程。
Q&A
Postgres 19 中 ON CONFLICT DO SELECT 的作用是什么?
ON CONFLICT DO SELECT 用于实现“获取或创建”模式:当插入发生冲突时,返回已存在的行,而不是执行更新或忽略;当无冲突时,正常插入并返回新行。它解决了之前使用 ON CONFLICT DO NOTHING 配合 RETURNING 无法返回现有行的问题。
Postgres 19 的 ON CONFLICT DO SELECT 支持哪些行锁?
ON CONFLICT DO SELECT 支持与普通 SELECT 相同的行级锁,包括 FOR UPDATE、FOR NO KEY UPDATE、FOR SHARE 和 FOR KEY SHARE,可以在返回现有行的同时锁定该行,防止并发修改。
使用 ON CONFLICT DO SELECT 时有哪些注意事项?
使用 ON CONFLICT DO SELECT 时,需要具备表的 SELECT 权限(不仅仅是 INSERT),并且必须包含 RETURNING 子句,否则会报错。此外,它还可以使用 WHERE 子句过滤返回的行。
Postgres 19 的 GROUP BY ALL 有什么作用?
GROUP BY ALL 会自动将 SELECT 列表中所有非聚合列(包括计算表达式)作为分组依据,无需手动列出所有列。它简化了 GROUP BY 查询,并支持窗口函数(窗口函数不会被当作分组键)。
GROUP BY ALL 可能带来什么潜在问题?
GROUP BY ALL 可能过于灵活,当 SELECT 列表新增列时,分组会自动包含新列,导致结果集列数变化,可能影响下游解析器或电子表格(它们可能按位置而非列名处理数据),且不会报错,增加了排查难度。
Postgres 19 的 COPY 如何输出 JSON 格式?
Postgres 19 的 COPY 新增 FORMAT JSON 选项,可以输出新行分隔的 JSON 对象(每行一个对象),也支持 FORCE_ARRAY 参数输出为单个 JSON 数组。它支持嵌套类型(如数组和 jsonb),但仅支持 COPY TO,不支持 COPY FROM。
COPY 输出 JSON 时,FORCE_ARRAY 参数有什么作用?
FORCE_ARRAY 参数使 COPY 输出一个完整的 JSON 数组,而不是新行分隔的 JSON 对象。这样整个输出是合法的 JSON 文档,便于直接交给 JSON 解析器或写入文件。