BULK INSERT 导入 CSV 易报错,因 SQL Server 不解析 CSV 语义,需手动处理路径权限、FIRSTROW、CODEPAGE、字段分隔符等;含引号或逗号时应预处理或改用导入向导。

BULK INSERT 确实能比逐行 INSERT 快几倍甚至几十倍,但直接用它导入 CSV 很容易报错——不是路径找不到,就是类型转换失败,或者第一行标题被当数据插进去。根本原因在于:SQL Server 从不把 CSV 当“标准格式”对待,它只认字符分隔的纯文本,且默认不支持标题行、引号包裹、混合编码等常见 CSV 特性。
为什么 BULK INSERT 导入 CSV 总是报错?
常见错误现象包括:Cannot bulk load because the file could not be opened(路径权限或 UNC 问题)、Invalid column number in the format file(字段数对不上)、Conversion failed when converting date/time(日期格式不一致)。
本质是 BULK INSERT 不解析 CSV 语义:它不会跳过标题行(除非显式指定 FIRSTROW),不会自动识别双引号包裹的字段,也不处理 Excel 保存的 UTF-8 BOM 或混合编码(如中文 Windows 下的 GBK/ANSI)。它只按你给的 FIELDTERMINATOR 和 ROWTERMINATOR 生硬切分。
- CSV 文件必须是纯文本(推荐用记事本另存为 UTF-8 无 BOM 或 ANSI)
- 首行如果是列名,必须加
FIRSTROW = 2,否则会当作数据插入 - 字段含逗号、换行或引号时,
BULK INSERT默认无法处理——它不支持 RFC 4180 标准 - 路径必须对 SQL Server 服务账户可见:本地路径要放在数据库服务器上,不能是开发机上的
C: empile.csv
最简可行的 BULK INSERT CSV 导入写法
假设目标表已存在,名为 sales_data,CSV 文件位于数据库服务器 D 盘根目录,内容不含引号、无空行、第一行为标题:
BULK INSERT sales_data FROM 'D:datasales.csv' WITH ( FIELDTERMINATOR = ',', ROWTERMINATOR = ' ', FIRSTROW = 2, CODEPAGE = '65001', -- 强制 UTF-8 KEEPNULLS );
关键点说明:
使用 qbo-mileage CLI 及用户凭证,从 Airtable、Outlook 或 Google Calendar 记录生成 QuickBooks Online 里程 CSV 文件。
-
FIRSTROW = 2是防止标题当数据的最低要求 -
CODEPAGE = '65001'对含中文的 CSV 几乎必加,否则乱码;若文件是 ANSI(Windows-1252),改用'ACP' -
KEEPNULLS防止空字符串被转成默认值(比如GETDATE()) - 别用
FORMAT = 'CSV'—— 它仅在 SQL Server 2017+ 且配合 Azure 存储时才有效,本地文件不支持
遇到字段含引号或逗号怎么办?
直接放弃 BULK INSERT。它没有原生引号解析能力。你有三个选择:
- 预处理 CSV:用 PowerShell 或 Python 去掉引号、转义逗号,再导入(适合一次性任务)
- 改用
OPENROWSET(BULK...)+ 格式文件(复杂但可控,需提前定义每列类型和偏移) - 回到图形化工具:SSMS 的导入向导底层会调用
Microsoft.ACE.OLEDB.12.0驱动,能正确识别 Excel/CSV 的引号逻辑,更省心
例如,用 OPENROWSET 绕过引号问题需先启用 Ad Hoc Distributed Queries,再写:
SELECT * FROM OPENROWSET( BULK 'D:datasales.csv', FORMATFILE = 'D:dataormat.xml', CODEPAGE = '65001' ) AS data;
但 format.xml 必须手工编写,描述每一列的宽度、类型、是否跳过等——这对临时导入来说,成本远高于用向导点几下。
权限和路径最容易被忽略的坑
错误信息 Cannot bulk load because the file could not be opened 90% 不是路径写错,而是权限问题:
- SQL Server 服务账户(不是你的 Windows 登录账户)必须对 CSV 文件所在目录有读取权限
- 如果路径是网络共享(UNC),必须用
\servershareile.csv,且 SQL Server 账户需有该共享的 NTFS 权限 - Azure SQL 数据库完全不支持本地路径,
FROM 'C:...'会直接报错——只能用 Azure Blob 存储 + SAS token - 即使路径正确,若 CSV 正被 Excel 打开,SQL Server 会因文件锁失败,报
Access is denied
真正卡住人的,往往不是语法,而是那个没给 SQL Server 服务账户加上的“读取”权限,或者忘了关掉 Excel。这些细节不验证,写十遍 BULK INSERT 都跑不通。

















