首页 游戏 软件 资讯 排行榜 专题
首页
数据库
PostgreSQL如何高效执行UPSERT操作_利用ON CONFLICT指令

PostgreSQL如何高效执行UPSERT操作_利用ON CONFLICT指令

热心网友
58
转载
2026-04-29

PostgreSQL ON CONFLICT:唯一可靠的原子UPSERT操作指南

PostgreSQL如何高效执行UPSERT操作_利用ON CONFLICT指令

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

在PostgreSQL的世界里,如果你想实现“有则更新,无则插入”的UPSERT操作,ON CONFLICT是那条唯一可靠、原子且可预测的路径。至于那些在业务层自己写的“先查询,再决定插入或更新”的逻辑,在并发场景下几乎注定会出问题,建议直接放弃尝试。

ON CONFLICT 必须基于唯一约束,否则直接报错

这里有个关键点需要明确:当你写下ON CONFLICT (email)时,PostgreSQL并不会自动为你创建索引。它只会检查email这一列是否已经定义了UNIQUE约束或是PRIMARY KEY。如果没有,那么等待你的将是明确的错误提示:

ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification

哪些是常见的误解和误操作呢?

  • 对着一张表的普通INDEX(非唯一索引)使用ON CONFLICT——行不通。
  • 对着一个仅有NOT NULL属性的列使用——同样行不通。
  • 表刚创建完,忘了给目标列加上UNIQUE(email)约束就直接执行SQL——结果就是报错。

验证方法其实很简单:在psql命令行中执行\d 表名,确认目标列旁边清晰地标记着UNIQUEPK

多唯一约束时,必须显式指定冲突目标

想象一张表同时拥有email UNIQUEphone UNIQUEid PRIMARY KEY三个唯一约束。如果你只写了ON CONFLICT (id),那么当email发生冲突时,语句依然会报错,而不会自动回退到其他约束进行处理。

正确的做法是二选一:

  • 使用列名:如果冲突只可能来自主键,那就明确指定ON CONFLICT (id)
  • 使用约束名:这种方式通常更安全,尤其当你需要响应特定列(如email)的冲突时。首先查询约束名:SELECT conname FROM pg_constraint WHERE conrelid = 'users'::regclass AND contype = 'u';,然后在语句中引用:ON CONFLICT ON CONSTRAINT users_email_key
  • 对于联合唯一约束,逻辑相同:例如定义了UNIQUE(user_id, product_id),就必须写ON CONFLICT (user_id, product_id)

DO UPDATE 里用 WHERE 条件要格外小心

很多人习惯在DO UPDATE后面加上WHERE products.status = 'active'这样的条件,意图是“只更新状态为有效的商品”。但这里有个至关重要的细节:这个WHERE子句是作用于原表行(即发生冲突的那一行)的,而不是作用于准备插入的新数据。一旦条件不成立,整个DO UPDATE操作就会被跳过——结果就是既没有插入新行,也没有更新旧行。更棘手的是,语句还会返回成功(例如INSERT 0 1),这种“静默失效”非常隐蔽,难以排查。

容易踩到的坑包括:

  • 忘记加WHERE条件,导致意外覆盖了历史状态。
  • 加了WHERE条件,却没意识到它可能导致整个UPSERT操作静默失败。
  • DO UPDATE SET中引用EXCLUDED虚拟表来获取新值时,误写成MySQL风格的VALUES()语法(PostgreSQL不支持这种写法)。

来看一个正确的写法示例:

INSERT INTO products (sku, price, status) VALUES ('IPHONE_15', 7999, 'active') ON CONFLICT (sku) DO UPDATE SET price = EXCLUDED.price, updated_at = NOW() WHERE products.status = 'active';

想拿到插入或更新后的 ID?RETURNING 必须配 QueryRow

这个场景很常见:在Go或Python程序中,开发者使用db.Query(... RETURNING id),然后直接调用rows.Scan(&id),却发现返回的id总是0。问题出在哪里?因为RETURNING子句最多只返回一行,而像Go的db.Query()方法要求必须先调用rows.Next()才能读取数据。

真正安全的做法只有这一种:

  • Go语言:必须使用db.QueryRow()。这个方法内部自动处理了单行结果集的逻辑,如果查询无结果,会返回sql.ErrNoRows错误。
  • Python (psycopg2):使用cursor.fetchone(),不要使用cursor.fetchall()
  • psql命令行:直接使用RETURNING *没问题,但在应用程序中不能假设总是返回多行。

还有一个最容易被忽略的关键点:即使语句触发了DO UPDATE(即执行了更新),RETURNING子句返回的也始终是当前行(即更新后的行)的值,而不是最初尝试插入的那些值。这一点在设计幂等性写入逻辑时,对于调试和理解行为至关重要。

来源:https://www.php.cn/faq/2391079.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

PS强制联网验证最新解释:索尼系统漏洞 防止退款后还能玩
游戏评测
PS强制联网验证最新解释:索尼系统漏洞 防止退款后还能玩

近期PS数字游戏强制联网验证风波:是漏洞修复,还是策略调整? 最近,不少PlayStation玩家遇到了一个颇为困扰的情况:自己库里的部分数字版游戏,开始要求每隔30天就必须联网验证一次。如果到期未验证,游戏就会被系统锁定,无法启动,直到玩家重新联网完成授权检查。这一现象并非个例,索尼官方客服也已确

热心网友
04.29
《Love and Deepspace》的玩家们正在热议一款画风似曾相识的全新恋爱游戏
游戏攻略
《Love and Deepspace》的玩家们正在热议一款画风似曾相识的全新恋爱游戏

《Silent Whispers》全新恋爱游戏公布,画风酷似《Love and Deepspace》,采用UE5引擎打造4K电影级画质,无抽卡模式,支持多平台免费游玩 今天,恋爱游戏领域迎来了一位新成员——《Silent Whispers》。消息一出,立刻在玩家社区中激起了涟漪,尤其是《Love a

热心网友
04.29
如何找出AWR中耗时最长的SQL_Elapsed Time排名与执行效率瓶颈
数据库
如何找出AWR中耗时最长的SQL_Elapsed Time排名与执行效率瓶颈

怎么看 AWR 报告里 SQL 的 Elapsed Time 排名 打开AWR报告,很多人会直奔“SQL ordered by Elapsed Time”部分,默认认为排在前面的就是“最慢”的SQL。但这里有个常见的理解误区:这个排名依据的是Elapsed Time,它统计的其实是SQL在快照期间所

热心网友
04.28
索尼实锤PS5强制联网验证!曾嘲讽Xbox如今活成对方
游戏评测
索尼实锤PS5强制联网验证!曾嘲讽Xbox如今活成对方

索尼PlayStation支持近日正式确认,PS5主机近期出现的一项全新数字版权管理(DRM)政策调整并非系统故障,而是官方有意为之的既定政策。 这项变动,从根本上改变了玩家离线游玩数字版游戏的方式,也在社交媒体上引发了轩然大波。 根据索尼官方的最新说明,这项政策主要针对2026年3月系统更新后购买

热心网友
04.28
Linux怎么查看进程消耗的VSS/RSS/PSS内存 Linux内存指标详解
系统平台
Linux怎么查看进程消耗的VSS/RSS/PSS内存 Linux内存指标详解

Linux怎么查看进程消耗的VSS RSS PSS内存 Linux内存指标详解 ps 命令只能看到 VSZ 和 RSS,看不到 PSS USS 说到排查内存问题,很多工程师的第一反应就是敲下 ps aux --sort -rss。这个命令确实能给出一个排序,但这里头其实有个关键限制:你看到的 VSZ

热心网友
04.28

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

Debian系统中如何配置Python异常处理
编程语言
Debian系统中如何配置Python异常处理

在Debian系统中配置Python异常处理 在Debian操作系统上为Python应用程序构建一套完善的异常处理机制,是确保服务长期稳定与可靠性的核心环节。这不仅仅是编写基础的try except语句,更涉及从错误捕获、日志记录到生产环境监控的一整套解决方案。本文将详细指导您如何在Debian

热心网友
04.29
Debian Python如何实现代码热更新
编程语言
Debian Python如何实现代码热更新

在Debian系统上实现Python代码的热更新 你是否希望你的Python应用能够在不中断服务的情况下完成版本迭代?对于要求高可用性的生产环境而言,实现代码热更新是一项至关重要的能力。在Debian Linux系统上,我们可以通过一套经过验证的技术组合来达成这一目标。其核心原理主要围绕以下几个关键

热心网友
04.29
Python在Debian上如何配置缓存机制
编程语言
Python在Debian上如何配置缓存机制

Debian系统Python缓存配置全攻略:从pip加速到应用性能优化 在Debian操作系统环境下为Python配置缓存机制,是提升开发与运行效率的关键步骤。本文将从两个核心维度展开:一是优化Python包管理器pip的下载缓存,二是为Python应用程序实现高效的数据缓存策略。两者虽目标一致——

热心网友
04.29
Debian系统中如何配置Python多线程
编程语言
Debian系统中如何配置Python多线程

Debian系统Python多线程配置完整指南 在Debian操作系统上实现Python多线程编程,是提升程序并发性能的关键技术。本文将系统性地讲解如何在Debian环境中正确配置Python多线程开发环境,并提供实用的代码示例与优化建议,帮助开发者高效利用多核处理器资源。 1 Python环境安

热心网友
04.29
Python在Debian上如何配置数据库连接
编程语言
Python在Debian上如何配置数据库连接

在Debian上配置Python数据库连接 想在Debian系统上让Python和数据库顺畅对话?这事儿其实没想象中那么复杂。只要跟着几个清晰的步骤走,你就能轻松搭建起连接桥梁。下面,咱们就来把整个过程拆解一遍。 1 安装数据库服务器 第一步,自然是得在Debian上把数据库服务给跑起来。这里以最

热心网友
04.29