跨链接服务器不同排序规则查询:单向正常另一方向报错原因咨询
问题背景
ServerA(SQL Server 2019 RTM)使用Latin1_General_BIN排序规则;ServerB(SQL Server 2016 SP1)使用SQL_Latin1_General_CP1_CI_AS排序规则。两台服务器的链接服务器属性完全一致:Use Remote Collation设为False,Collation Compatible设为False,Collation Name为空。
在ServerA上执行以下查询时报错:
Cannot resolve the collation conflict between "Latin1_General_BIN" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
查询语句:
SELECT Count(1) FROM ServerA.DatabaseA.dbo.TableA INNER JOIN ServerB.DatabaseB.dbo.TableB On TableA.ID = TableB.ID;
但在ServerB上执行相同查询却能正常返回结果。已知通过COLLATE DATABASE_DEFAULT可解决报错,现需明确为何同一查询在两台服务器上表现不同。
原因分析
这种差异核心在于SQL Server不同版本对跨链接服务器查询的排序规则检查逻辑不同:
2019版本的严格规则校验
当在ServerA(2019版本)执行查询时,查询计划由2019引擎生成。由于Use Remote Collation和Collation Compatible均为False,引擎会严格校验参与连接的两列排序规则:本地TableA.ID的Latin1_General_BIN与远程TableB.ID的SQL_Latin1_General_CP1_CI_AS属于完全不同的排序规则体系,既没有显式指定转换规则,也没有属性层面的兼容设置,因此直接触发排序规则冲突报错。2016版本的宽松兼容处理
在ServerB(2016 SP1版本)执行查询时,旧版本引擎对跨链接服务器的排序规则冲突处理存在兼容逻辑。即使链接服务器属性未开启兼容,引擎会默认尝试将远程列的排序规则隐式转换为本地服务器的排序规则(SQL_Latin1_General_CP1_CI_AS),或者跳过部分严格的冲突检查,从而让查询正常执行。版本迭代后的规则收紧
SQL Server 2019对跨实例查询的排序规则一致性做了严格优化,目的是避免隐式转换带来的性能损耗或结果不一致问题;而2016版本的规则相对宽松,保留了旧版的兼容行为,这就导致了同一查询在不同版本服务器上的结果差异。
内容的提问来源于stack exchange,提问作者mezzanayne

