SSIS ADO.NET Destination数据流任务报错:Received an invalid column length
问题场景
处理多个SSIS包时,控制流中Union All上方的Script任务从内存Recordsets提取数据,所有数据结构一致,但ADO.NET Destination任务报错:
"An exception has occurred during data insertion, the message returned from the provider is: Received an invalid column length from the bcp client for colid 10."
限制记录数为SELECT TOP 12610 * FROM FormSubmissions时正常,增至12611则报错;调整缓冲区设置(DefaultBufferMaxRows=500、DefaultBufferSize=7500000)后处理结果变化,但样本量低于12611仍正常。尝试提取第12610条之后的记录预览正常,但问题未解决,还出现附加错误:
- System.Runtime.InteropServices.COMException (0xC0047020): Exception from HRESULT: 0xC0047020
- [SSIS.Pipeline] Error: SSIS Error Code DTS_E_PROCESSINPUTFAILED...
排查与解决步骤
1. 定位colid 10对应的目标列
colid对应数据库表的系统列ID,执行以下SQL查询目标表的列顺序与ID:
SELECT name AS 列名, column_id AS 列ID FROM sys.columns WHERE object_id = OBJECT_ID('你的目标表名') ORDER BY column_id
找到column_id=10的列,确认该列在目标表中的定义长度(如varchar(100)),再检查数据流中对应列的输出长度是否匹配。
2. 排查第12611条及后续记录的异常数据
不要仅依赖预览,直接查询目标列的实际长度,找出超长数据:
SELECT 目标列名, LEN(目标列名) AS 实际字符长度, DATALENGTH(目标列名) AS 实际字节长度 -- 若为Unicode类型用这个 FROM ( SELECT * FROM FormSubmissions ORDER BY 主键列 OFFSET 12610 ROWS FETCH NEXT 1000 ROWS ONLY ) AS t WHERE LEN(目标列名) > 目标表列定义的最大长度 -- 替换为实际数值
如果找到超长数据,可选择:
- 修改目标表列的长度,匹配实际数据需求
- 在数据流中添加派生列转换,用
SUBSTRING(目标列名, 1, 最大允许长度)截断超长内容 - 添加条件拆分转换,过滤掉数据超长的异常行
3. 解决缓冲区调整引发的附加错误
0xC0047020和DTS_E_PROCESSINPUTFAILED错误多因资源不足或组件超时导致:
- 进一步降低
DefaultBufferMaxRows(如设为100),同时保证DefaultBufferSize不超过10MB(10485760),避免内存过载 - 调整ADO.NET Destination的
BatchSize属性为较小值(如100),减少单次批量插入的数据量 - 检查Script任务中读取Recordset的逻辑,确保用完Recordset后及时释放资源(如调用
Recordset.Close()、释放COM对象)
4. 替代Script任务读取Recordset的方案(可选)
若Script任务可能引入隐式转换问题,可尝试用Execute SQL Task配合OLE DB Source读取Recordset:
- 在Execute SQL Task中,将Recordset变量映射为输出参数(结果集设为“完整结果集”)
- 在OLE DB Source中选择“SQL命令”模式,用
SELECT * FROM ?读取该Recordset变量,避免Script任务的自定义逻辑可能带来的类型/长度偏差
内容的提问来源于stack exchange,提问作者Jacques

