SSIS包导入CSV至SQL Server失败且错误行无法重定向求助
解决SSIS导入混合引号CSV时的分隔符错误问题
这个坑我之前踩过好几次!你遇到的问题本质是SSIS平面文件连接管理器的默认解析逻辑搞不定混合引号格式的CSV——也就是部分字段用双引号包裹、部分不用的情况,尤其是当无引号的字段里包含逗号时,SSIS会误把这个逗号当成列分隔符,直接抛出找不到列分隔符的错误,而且这种属于数据源解析阶段的致命错误,错误行重定向根本不会触发,因为数据还没进入转换环节就挂了。
下面给你几个靠谱的解决办法,按优先级排序:
方法一:修改平面文件连接管理器的核心设置(最简单)
这是最优先尝试的方案,90%的情况都能解决:
- 打开你的平面文件连接管理器,切换到常规选项卡,确认格式是「分隔」
- 切到列选项卡:
- 把「文本限定符」设置为双引号
" - 关键操作:取消勾选「始终检查限定符」
- 为啥要这么做?默认勾选的话,SSIS会认为所有字段都必须用引号包裹,遇到没引号的字段里的逗号就直接混乱;取消后,它会智能识别:带引号的字段里的逗号会被当成内容,不带引号的字段会读到下一个未被引号包裹的逗号为止。
- 把「文本限定符」设置为双引号
- 设置完后点击「预览」,看看之前报错的行能不能正常解析。
方法二:用脚本组件自定义数据源(最灵活)
如果方法一还是搞不定(比如CSV格式特别奇葩),就用脚本组件自己写解析逻辑,完全掌控每一行的处理:
- 在数据流任务里添加「脚本组件」,选择「数据源」类型
- 在脚本编辑器的「输入和输出」选项卡,定义好输出列(和你的目标表列对应)
- 切换到「脚本」选项卡,编辑脚本(以C#为例),在
CreateNewOutputRows方法里写解析逻辑:using System.IO; using System.Text.RegularExpressions; using System.Collections.Generic; public override void CreateNewOutputRows() { // 替换成你的CSV文件路径 string csvPath = @"C:\YourSourceFile.csv"; // 预期的列数,根据你的实际情况调整 int expectedColumnCount = 5; // 逐行读取文件 foreach (string line in File.ReadAllLines(csvPath)) { // 用正则匹配所有字段,支持带引号和不带引号的情况 MatchCollection fieldMatches = Regex.Matches(line, @"(?<=^|,)(?:""([^""]*)""|([^,]*))(?=,|$)"); List<string> fieldList = new List<string>(); foreach (Match match in fieldMatches) { // 优先取带引号的内容,没有的话取不带引号的部分 string fieldValue = match.Groups[1].Success ? match.Groups[1].Value : match.Groups[2].Value; fieldList.Add(fieldValue); } // 处理正常行 if (fieldList.Count == expectedColumnCount) { Output0Buffer.AddRow(); Output0Buffer.ColumnX = fieldList[0]; Output0Buffer.ColumnY = fieldList[1]; // ...其他列依次赋值 } // 处理异常行,重定向到错误输出 else { Output0ErrorBuffer.AddRow(); Output0ErrorBuffer.ErrorLineContent = line; Output0ErrorBuffer.ErrorReason = $"字段数量不匹配,预期{expectedColumnCount}个,实际{fieldList.Count}个"; } } } - 保存脚本后,把脚本组件的输出连接到目标表,错误输出连接到错误文件,这样就能正常处理所有行,包括异常行。
方法三:预处理CSV文件(临时应急方案)
如果不想改SSIS包,可以先把CSV预处理成所有字段都带引号的格式:
- 用PowerShell脚本批量处理,示例代码:
$sourcePath = "C:\OriginalFile.csv" $targetPath = "C:\ProcessedFile.csv" $content = Get-Content $sourcePath $processedContent = $content | ForEach-Object { # 给不含引号的字段加上双引号(已带引号的跳过) [Regex]::Replace($_, '(?<=^|,)([^,"]+)(?=,|$)', '"$1"') } $processedContent | Out-File $targetPath -Encoding UTF8 - 然后用处理后的文件作为SSIS的数据源,默认的平面文件源就能正常解析了。
内容的提问来源于stack exchange,提问作者S.Jose




