如何修复 SQL Server 查询中的排序规则冲突?

Posted

技术标签:

【中文标题】如何修复 SQL Server 查询中的排序规则冲突?【英文标题】:How to fix a collation conflict in a SQL Server query? 【发布时间】:2013-12-30 22:00:07 【问题描述】:

我正在处理一个视图,其中我在来自两个不同服务器的两个表上使用内部联接。我们正在使用链接服务器。运行查询时,我收到以下消息:

无法解决等于操作中“SQL_Latin1_General_CP1_CI_AS”和“Arabic_CI_AS”之间的排序规则冲突。

我对排序规则了解不多。通过互联网搜索,我找到了使用COLLATE 的解决方案,但COLLATE 的概念对我来说并不清楚。它会改变任何数据库的任何东西吗?我正在寻找一种解决方案,而不需要对数据库进行任何更改。

欢迎任何关于这些概念的好的学习材料。

【问题讨论】:

你能展示你正在处理的 SQL 代码吗? 【参考方案1】:

您可以通过将查询中使用的排序规则强制为特定排序规则来解决此问题,例如SQL_Latin1_General_CP1_CI_ASDATABASE_DEFAULT。例如:

SELECT MyColumn
FROM FirstTable a
INNER JOIN SecondTable b
ON a.MyID COLLATE SQL_Latin1_General_CP1_CI_AS = 
b.YourID COLLATE SQL_Latin1_General_CP1_CI_AS

在上述查询中,a.MyID 和 b.YourID 将是具有基于文本的数据类型的列。使用COLLATE 将强制查询忽略数据库上的默认排序规则,而是使用提供的排序规则,在本例中为SQL_Latin1_General_CP1_CI_AS

基本上这里发生的事情是每个数据库都有自己的排序规则,“为您的数据提供排序规则、大小写和重音敏感属性”(来自http://technet.microsoft.com/en-us/library/ms143726.aspx)并适用于具有文本数据类型的列,例如VARCHARCHARNVARCHAR 等。当两个数据库具有不同的排序规则时,如果不解决两个不同排序规则之间的冲突,就无法使用等于 (=) 之类的运算符比较文本列。

【讨论】:

谢谢你。我正在使用 COLLATE 更新我的代码。如果有任何问题,我会告诉你。因此,这意味着数据库级别不会更改任何内容,并且此 COLLATE 将仅在 SQL 脚本中完成。 有趣的是,到目前为止,我认为我必须更改数据库级别的排序规则才能使 em 匹配,但不知道我可以使用 COLLATE 在查询中匹配 em!谢谢,这为我省去了很多麻烦。 解释得很好,谢谢@rory.ap 您不需要为比较的双方提供提示。 IE。这样就足够了:ON a.MyID = b.YourID COLLATE SQL_Latin1_General_CP1_CI_AS【参考方案2】:

我通过将查询包装在另一个查询中解决了类似的问题...

初始查询正在查找给出单独的输出列,其中一些列来自具有 Max 或 Sum 函数的子查询,而其他列则具有“不同”或大小写替换等。

我在尝试使用...创建单个输出字段后遇到排序错误

select
rtrim(field1)+','+rtrim(field2)+','+...

查询会在我写的时候执行,但是保存sql并重新加载后会出现错误。

用类似...的东西来修复它

select z.field1+','+z.field2+','+... as OUTPUT_REC
from (select rtrim(field1), rtrim(field2), ... ) z

某些字段是子查询的“最大值”,如果为 null,则使用大小写替换,其他字段是日期字段,还有一些是左连接(可能为 NULL)...换句话说,混合字段类型。我相信这是由于操作系统排序规则和数据库排序规则略有不同引起的问题的原因,但是通过在最终选择之前将所有内容转换为修剪后的字符串,它会在 SQL 中对其进行排序。

【讨论】:

【参考方案3】:

如果数据库由您维护,则只需创建一个新数据库并从旧数据库导入数据。排序问题解决了!!!!!!

【讨论】:

点评来源: 嗨,这篇文章似乎没有为问题提供quality answer。请编辑您的答案并改进它,或者将其作为评论发布。【参考方案4】:

我的排序规则有问题,因为我的大多数表都带有Modern_Spanish_CI_AS,但我从另一个数据库继承或复制的一些表有SQL_Latin1_General_CP1_CI_AS 排序规则。

就我而言,解决问题的最简单方法如下:

    我创建了一个表的副本,这些表是“拉丁美洲,使用脚本表作为...” 新表显然获得了我数据库的“现代西班牙语”排序规则 我已将“拉丁美洲”表的数据复制到新表中,删除了旧表并重命名了新表。

我希望这对其他用户有所帮助。

【讨论】:

【参考方案5】:

除了接受的答案,您可以使用DATABASE_DEFAULT 作为编码。

这允许数据库为您做出选择,并且您的代码变得更加可移植。

SELECT MyColumn
FROM 
    FirstTable a
        INNER JOIN SecondTable b
            ON a.MyID COLLATE DATABASE_DEFAULT = b.YourID COLLATE DATABASE_DEFAULT

【讨论】:

以上是关于如何修复 SQL Server 查询中的排序规则冲突?的主要内容,如果未能解决你的问题,请参考以下文章

SQL server中如何更改排序规则

SQL Server 案例/排序规则问题

使用 SC 排序规则的 SQL Server Unicode 查询

SQL Server转换数据库的排序规则

EF Core 中的 SQL Server 排序规则

Sql Server - 使用排序规则