sql server 2019批量插入数据,优先用insert into ... values(...),(...)(多值语法),500行以内够快够稳;超1000行必须切sqlbulkcopy或bulk insert,否则性能断崖下跌。

直接说结论:SQL Server 2019 批量插入数据,**优先用 INSERT INTO ... VALUES (...), (...), ...(多值语法)**,500 行以内够快、够稳、够简单;超过 1000 行,就该切到 SqlBulkCopy 或 BULK INSERT,否则性能断崖式下跌。
INSERT INTO ... VALUES 多行写法(适合 ≤500 行)
这是最常用也最容易上手的方式,SQL Server 2008 起原生支持,2019 完全兼容。它把多组值打包进一条语句,避免循环开销和网络往返。
- 必须显式指定列名,不能省略:
INSERT INTO actor (actor_id, first_name, last_name) VALUES (1,'Tom','Hanks'), (2,'Meryl','Streep'); - 单条语句最多支持 1000 个 value 元组(SQL Server 限制),超了会报错
Incorrect syntax near ','或Too many arguments specified for function - 如果表有自增主键(
IDENTITY),别在VALUES里写它——除非你开了SET IDENTITY_INSERT table_name ON - 字符串里含单引号要转义:写成
'O''Connor',不是'O\'Connor'
INSERT SELECT UNION ALL(适合动态拼接或跨源组合)
当你需要从不同逻辑生成数据、或字段值依赖计算/常量时,比纯 VALUES 更灵活,但性能略低于多值写法(因多了执行计划解析开销)。
- 语法结构清晰:
INSERT INTO actor (actor_id, first_name, last_name) SELECT 1,'Tom','Hanks' UNION ALL SELECT 2,'Meryl','Streep' UNION ALL SELECT 3,'Leonardo','DiCaprio'; - 每条
SELECT必须列数、类型、顺序完全一致,否则报错All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists - 不支持直接用变量替换字段值(比如
SELECT @id, @name),得包装成子查询或 CTE,否则容易触发参数嗅探问题
SqlBulkCopy(C# 场景,≥1000 行强推)
这是 .NET 应用往 SQL Server 2019 写大量数据的黄金标准,底层绕过 T-SQL 解析,直通存储引擎,速度通常是 INSERT 的 5–10 倍。
- 必须用
DataTable或IDataReader作数据源,不能传 List - 默认不触发约束和触发器,加
bulkCopy.EnableStreaming = true可降低内存占用(尤其处理百万级数据) - 目标表若已有索引,插入前建议
DROP INDEX,完事后重建——实测可提速 30%~60%,尤其对宽表 - 别忽略
SqlBulkCopy.BatchSize:设为 10000 左右较平衡,太小(如 100)导致批次过多,太大(如 100000)易触发 tempdb 压力或事务日志暴涨
BULK INSERT(文件导入场景,需注意权限和路径)
当你数据已在 CSV/TXT 文件里,且能访问数据库服务器本地磁盘时,BULK INSERT 是最快路径,但部署约束多,容易卡在第一步。
-
FROM 'D:\data\actors.csv'中的路径是 SQL Server 进程视角的本地路径,不是你客户端机器的路径——常见错误是填C:\...却没在数据库服务器上放文件 - 执行用户必须有
ADMINISTER BULK OPERATIONS权限,或属于sysadmin角色,普通db_owner不够 - 字段分隔符默认是
\t(制表符),CSV 要显式写FIELDTERMINATOR = ',',否则全塞进第一列 - 遇到乱码先查
CODEPAGE:中文 Windows 系统常用CODEPAGE = 'ACP',Linux 生成的 UTF-8 文件得用CODEPAGE = '65001'
真正难的不是选哪种方法,而是判断“多少算多”——500 行在低配虚拟机上可能就卡顿,而 5000 行在 SSD+32G 内存的物理机上用 VALUES 也跑得动。别迷信数字,用 SET STATISTICS IO ON 和 SET STATISTICS TIME ON 实测,看逻辑读和毫秒数说话。











