You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中ON CONFLICT DO NOTHING时如何返回对应行?

解决PostgreSQL INSERT ON CONFLICT时始终返回行的问题

针对你的需求,在PostgreSQL 17.5中可以通过两种方式实现无论冲突是否触发都返回完整行的效果:

方案1:利用ON CONFLICT DO UPDATE(无实际修改)

通过指定冲突的唯一约束列,执行一个无实际数据变更的UPDATE操作,这样RETURNING子句会在冲突时返回现有行,插入成功时返回新行:

INSERT INTO product (name, unit, standard_code)
VALUES ('test111', 'BOX', 'ISO-8601')
ON CONFLICT (name, unit, standard_code) DO UPDATE
SET name = EXCLUDED.name  -- 设置为原值,无实际数据修改
RETURNING *;

说明

  • 这里明确指定冲突的唯一约束列(name, unit, standard_code),对应表中定义的uq_product_name唯一约束
  • EXCLUDED指代插入语句中准备插入的行,设置name = EXCLUDED.name不会改变现有数据,但会触发RETURNING返回冲突行

方案2:使用WITH子句结合UNION ALL

先尝试插入,若插入无返回结果(触发冲突),则查询现有行:

WITH inserted AS (
    INSERT INTO product (name, unit, standard_code)
    VALUES ('test111', 'BOX', 'ISO-8601')
    ON CONFLICT DO NOTHING
    RETURNING *
)
SELECT * FROM inserted
UNION ALL
SELECT * FROM product
WHERE (name, unit, standard_code) = ('test111', 'BOX', 'ISO-8601')
AND NOT EXISTS (SELECT 1 FROM inserted);

说明

  • inserted CTE执行原插入逻辑,返回新插入的行(无冲突时)
  • 后续通过UNION ALL组合结果:若inserted为空(冲突触发),则查询现有行;否则只返回插入的行

两种方案中,方案1性能更优,仅需一次SQL执行;方案2逻辑更直观,不会产生任何更新操作(即使是无意义的)。

内容的提问来源于stack exchange,提问作者Aleksei Khatkevich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 23:38:13