BULK INSERT从CSV导入SQL表无报错但影响0行问题排查
Windows环境下SQL Server的BULK INSERT对ROWTERMINATOR = '\n'的默认解析逻辑是匹配CRLF(\r\n,即Windows系统标准换行格式),不会识别单独的LF(\n,类Unix系统标准换行格式)为有效行终止符。
该场景下0行影响的触发逻辑非常明确:FTP上传的文件为纯LF换行,BULK INSERT执行时无法识别任何行分隔标记,会把整个文件判定为第1行(表头行),配置FIRSTROW = 2跳过表头时就直接跳过了全部内容,整个语句无语法错误因此不报错,但最终插入行数为0。手动复制内容新建文件时,Windows系统会自动把所有换行替换为CRLF格式,因此插入可以正常执行。
方案1:修改BULK INSERT行终止符配置,精准匹配LF换行
不要使用转义字符'\n'作为行终止符,改用十六进制值显式指定LF为分隔符,修改后的导入脚本如下:BULK INSERT dbo.t_process_order_import FROM 'C:\Root\Product Data\H888 ProcOrd.csv' WITH ( FIRSTROW = 2, -- 跳过表头行 FIELDTERMINATOR = '|', ROWTERMINATOR = '0x0A', -- 显式匹配纯LF换行符 TABLOCK )该写法可以直接适配纯LF格式的CSV文件,不需要对源文件做任何修改。
方案2:调整FTP传输规则,自动适配Windows换行格式
将CSV文件的FTP传输模式从二进制模式改为ASCII模式,FTP协议的ASCII传输模式会自动根据目标服务器的操作系统类型转换换行格式,把源端的LF换行自动转换为Windows兼容的CRLF格式,文件上传后直接用原有脚本导入即可,不需要额外调整SQL逻辑。注意不要用二进制模式传输纯文本类的CSV文件,该模式会原封不动保留源文件的所有格式标记,包括不兼容的换行符。方案3:导入前增加自动化预处理步骤转换换行格式
如果受SQL Server版本、FTP配置限制无法使用前两个方案,可以在导入任务前加一步自动化脚本转换换行格式,直接集成到作业调度流中,不需要手动操作文件。以PowerShell为例,转换脚本如下:$targetFile = 'C:\Root\Product Data\H888 ProcOrd.csv' $fileContent = [System.IO.File]::ReadAllText($targetFile) # 统一将任意换行格式替换为Windows标准CRLF $standardContent = $fileContent -replace "`r?`n", "`r`n" # 保持原文件编码写回,避免编码不匹配问题 [System.IO.File]::WriteAllText($targetFile, $standardContent, [System.Text.Encoding]::Default)
如果CSV文件字段内容中本身包含内嵌换行,需要在SQL Server 2017及以上版本的BULK INSERT配置中增加FIELDQUOTE = '"'参数(根据实际使用的文本限定符调整值),避免把字段内部的换行误判为行终止符导致导入数据错位。
内容的提问来源于stack exchange,提问作者HA-11-SIAWN

