讲师中心 微信公众号
AI工具推荐 视频效率加速

SQL Server如何实现批量Upsert的高性能方案_利用Merge语句

阿浩君_7575

阿浩君_7575

发布时间:2026-04-21 12:28:12

|

359人浏览过

|

来源于php中文网

原创

SQL Server 的 MERGE 语句必须同时包含 WHEN MATCHED 和 WHEN NOT MATCHED 分支,禁止省略任一分支;需确保 USING 子句返回结果集、ON 条件避免 NULL 比较、批量操作使用临时表加索引、并发时添加 HOLDLOCK 提示,并严格满足目标表的 NOT NULL 约束。

sql server如何实现批量upsert的高性能方案_利用merge语句

MERGE 语句必须配对 WHEN MATCHED 和 WHEN NOT MATCHED

SQL Server 的 MERGE 不允许只写一半逻辑。哪怕你业务上「只更新不插入」或「只插入不更新」,也得显式写出两个分支,否则直接报错:The MERGE statement attempted to UPDATE or DELETE the same row more than once 或语法拒绝。常见错误是漏掉 WHEN NOT MATCHED,或把 INSERT 写成 INSERT INTO ... SELECT 却没加 VALUES 子句。

  • WHEN NOT MATCHED THEN INSERT (col1, col2) VALUES (s.col1, s.col2) —— 必须用 VALUES,不能省略
  • 源数据(USING 子句)必须返回结果集,USING (VALUES (@id, @name)) AS s(id, name) 合法,但裸写 USING (@id, @name) 会报错
  • ON 条件里避免 NULL 比较:例如 t.id = s.id 在任一为 NULL 时恒为 UNKNOWN,导致匹配失败;应提前过滤或改用 t.id = s.id OR (t.id IS NULL AND s.id IS NULL)(需确保业务允许空值主键)

批量 Upsert 必须走临时表 + 索引优化

单行循环执行 MERGE(比如 Python 中 for row in df: cursor.execute(...))在万级以上数据量下极慢,本质是网络往返 + 解析开销叠加。真正高性能的做法是:先把数据批量载入临时表,再用 MERGE 一次处理整个结果集。

  • 创建本地临时表:CREATE TABLE #staging (id INT, name NVARCHAR(50), url VARCHAR(200))
  • 用 bcp、SqlBulkCopy 或 pymssql 的 executemany 批量灌入数据(比逐行快 10–100 倍)
  • ON 字段必须有索引:目标表的匹配列(如 id)要是主键或唯一索引;临时表的对应列也建议建索引(尤其数据量 > 10k)
  • 避免在 ON 中写函数或表达式,例如 UPPER(t.email) = UPPER(s.email) 会让索引失效

并发安全要加 HOLDLOCK,别信默认隔离级别

高并发场景下,多个 MERGE 同时运行可能因幻读导致重复插入或丢失更新。SQL Server 默认的 READ COMMITTED 不足以保护 MERGE 的匹配判断过程。必须显式加锁提示。

  • 在目标表别名后加 WITH (HOLDLOCK),等价于 SERIALIZABLE,确保整个 MERGE 过程串行化
  • 错误写法:MERGE INTO users AS t USING ... —— 缺少锁提示,高并发时大概率出问题
  • 正确写法:MERGE INTO users WITH (HOLDLOCK) AS t USING ...
  • 注意:HOLDLOCK 会延长锁持有时间,若批量数据跨分钟级,要考虑阻塞影响

字段对齐和 NOT NULL 约束最容易被忽略

MERGE 的 INSERT 分支和 UPDATE 分支字段不要求顺序一致,但每个分支都必须满足目标表的约束。最常踩的坑是:目标表某列为 NOT NULL,而 INSERT 分支里没提供值,或传了 NULL,直接报错中断整个语句。

  • 检查目标表 DDL:SELECT COLUMN_NAME, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'your_table'
  • INSERT 分支必须显式列出所有 NOT NULL 列,并确保值非空(包括默认值列也要显式写,除非定义了 DEFAULT 且未禁用)
  • 如果源数据某些字段可能为空,INSERT 分支里用 ISNULL(s.col, 'default') 或 CASE 处理,别指望数据库自动补

真正卡性能的地方往往不是 MERGE 本身,而是 ON 条件能不能走索引、临时表有没有建好、并发时锁没加对——这些点没调好,再标准的语法也扛不住批量压力。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

相关专题

更多
sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

4971

2023.08.11

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2485

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

3761

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

2711

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

907

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

2407

2023.10.09

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

2427

2023.10.16

vb连接access数据库的方法
vb连接access数据库的方法

vb连接access数据库方法:1、使用ADO连接,首先导入System.Data.OleDb模块,然后定义一个连接字符串,接着创建一个OleDbConnection对象并使用Open() 方法打开连接;2、使用DAO连接,首先导入 Microsoft.Jet.OLEDB模块,然后定义一个连接字符串,接着创建一个JetConnection对象并使用Open()方法打开连接即可。

2813

2023.10.16

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

100

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
零基础精通 PS 视频教程
零基础精通 PS 视频教程

共268课时 | 119.4万人学习

前端工程师必备技能—PS切图
前端工程师必备技能—PS切图

共11课时 | 2.2万人学习

麦子学院Photoshop切片视频教程
麦子学院Photoshop切片视频教程

共13课时 | 4.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn