SQL中的错误处理及错误绕过:链接服务器插入操作报错如何解决
OLE DB provider 'MSDASQL' for linked server 'ServerName' returned data that does not match expected data length for column '[ServerName]..[SQLUser].[STUSER].USERID'. The (maximum) expected data length is 4, while the returned data length is 5.
报错原因
该报错是SQL Server本地缓存的链接服务器USERID字段元数据最大长度为4,但远程数据源实际返回的该字段数据长度为5导致的。普通SELECT查询不会触发严格的元数据长度校验因此可以正常返回结果,而INSERT操作需要校验数据和目标/元数据的匹配性,因此触发报错。以下方案均无需修改远程源表结构即可解决问题:
可行解决方案
【最稳妥通用方案】使用
OPENQUERY查询远程数据并显式转换字段类型
直接在查询阶段将USERID字段强制转换为匹配实际长度的类型,覆盖本地缓存的错误元数据后再执行插入。示例代码:INSERT INTO 你的本地目标表 (USERID, 其他字段列表) SELECT CAST(USERID AS VARCHAR(5)) AS USERID, 其他字段列表 FROM OPENQUERY(ServerName, 'SELECT USERID, 其他字段列表 FROM SQLUser.STUSER')你可以根据实际业务需要将
VARCHAR(5)调整为更长的字符类型,OPENQUERY会直接把查询语句发送到远程服务器执行,返回结果后再做类型转换,完全规避本地元数据校验问题。调整本地目标表字段长度
你仅被限制不能修改远程源表结构的前提下,直接把本地接收数据的目标表USERID字段长度调整为5或更长,匹配远程返回的实际数据长度即可。显式指定查询结果集结构
如果你需要使用四部分名称([ServerName]..[SQLUser].[STUSER])格式查询,可以通过WITH RESULT SETS强制定义返回字段的类型和长度,覆盖本地缓存的错误元数据:INSERT INTO 你的本地目标表 (USERID, 其他字段列表) SELECT * FROM [ServerName]..[SQLUser].[STUSER] WITH RESULT SETS ( (USERID VARCHAR(5), 其他字段名 对应字段类型) )刷新链接服务器元数据缓存
如果远程源表的USERID字段实际长度已经更新为5,只是本地缓存的元数据未同步,可以执行命令刷新缓存:EXEC sp_refreshsqlmodule '[ServerName]..[SQLUser].[STUSER]' -- 部分SQL Server版本也可以删除后重新创建同名链接服务器,触发元数据重新拉取
内容的提问来源于stack exchange,提问作者Tyork

