为什么SQL_Latin1_General_CP1_CI_AS在下划线之前对数字符号进行排序?

时间:2015-09-21 22:37:37

标签: sql-server sorting unicode collation

跟进https://stackoverflow.com/a/32233795/14731后,我惊讶地发现:

DECLARE @SampleData TABLE (ANSI VARCHAR(50), UTF16 NVARCHAR(50));
INSERT INTO @SampleData (ANSI, UTF16) VALUES 
    ('##MS_PolicyTsqlExecutionLogin##', N'##MS_PolicyTsqlExecutionLogin##'),
    ('_gaia', N'_gaia');

SELECT sd.ANSI AS [ANSI-SQL_Latin1_General_CP1_CI_AS]
FROM   @SampleData sd
ORDER BY sd.ANSI COLLATE SQL_Latin1_General_CP1_CI_AS ASC;

SELECT sd.UTF16 AS [UTF16-SQL_Latin1_General_CP1_CI_AS]
FROM   @SampleData sd
ORDER BY sd.UTF16 COLLATE SQL_Latin1_General_CP1_CI_AS ASC;

结果:

ANSI-SQL_Latin1_General_CP1_CI_AS
-------------------------------------
##MS_PolicyTsqlExecutionLogin##
_gaia

UTF16-SQL_Latin1_General_CP1_CI_AS
-------------------------------------
##MS_PolicyTsqlExecutionLogin##
_gaia

当根据" Why doesn't ICU4J match UTF-8 sort order?"时,Unicode结果应该是相反的顺序。为什么会这样?

2 个答案:

答案 0 :(得分:1)

首先要做的事情是:关联的问题 - Why doesn't ICU4J match UTF-8 sort order? - 尚未证明完全正确; - )。

除了相关信息外,让我们看看各个部分:

  1. VARCHAR字段COLLATE SQL_Latin1_General_CP1_CI_AS

    这将主要基于ASCII值进行排序,对于字母字符,将根据代码页1(a.k.a. Code Page 1252)中定义的规则进行排序和比较。

    #字符是ASCII码35,而_字符是ASCII码95.这些字符不是字母字符,所以应该假设它们会在#出现时排序。执行ASC结束订单,正如您在此处所做的那样。

  2. NVARCHAR字段COLLATE SQL_Latin1_General_CP1_CI_AS

    这将根据Unicode规则进行排序。 Unicode中没有代码页,但可能是文化差异,它们会覆盖默认的排序规则和排序。并且,为了使事情变得更有趣,基本规则和文化/语言环境特定的覆盖可以(并且确实)多年来发生变化。软件供应商并不总是能够快速实施新版本的标准。这与在不同时间点实现不同W3C细节的各种浏览器没有什么不同。 SQL Server的主要更新来自2008版,它引入了100一系列排序规则。 SQL Server 2012引入了90100系列的变体,以_SC结尾,用于处理补充字符(即UCS-2集之外的其余UTF-16字符)。

    回到刚才提到的事情,每个语言环境/文化可以指定任何规则的覆盖(而不仅仅是排序规则)。当前版本28(仅在4天前发布!!),具有以下美国语言环境(位于:http://www.unicode.org/repos/cldr/tags/release-27/common/collation/en_US_POSIX.xml

    <collation type="standard">
      <cr>
      <![CDATA[
        &A<*'\u0020'-'/'<*0-'@'<*ABCDEFGHIJKLMNOPQRSTUVWXYZ<*'['-'`'<*abcdefghijklmnopqrstuvwxyz <*'{'-'\u007F'
      ]]>
      </cr>
    </collation> 
    

    阅读新语法并不是一件容易的事,但我不认为他们正在重新排序任何这些标点字符。如果你去他们的Collation Charts然后点击4个链接(从顶部,左边开始),对于“标点符号”,它肯定会列出“_”作为除了一个字符之外的所有字符。

    如果我们返回几个版本,我们会找到(发现于:http://www.unicode.org/repos/cldr/tags/release-23/common/collation/en_US_POSIX.xml):

    <collation type="standard">
      <rules>
        <reset>A</reset>
        <pc>!"#$%&'()*+,-./</pc>
        <pc>0123456789:;<=>?@</pc>
        <pc>ABCDEFGHIJKLMNOPQRSTUVWXYZ</pc>
        <pc>[\]^_`</pc>
        <pc>abcdefghijklmnopqrstuvwxyz</pc>
        <pc>{|}~</pc>
      </rules>
    </collation> 
    

    现在它 看起来像是重新排序了它,并且与ASCII值的顺序相同?

    如果您将URL更改为指向版本24,那将看起来就像当前版本28 XML。

    根据此处CLDR Releases/Downloads发布的发布日期,版本24在2013年出现,在100系列排序规则编码之后很久。

答案 1 :(得分:0)

事实证明,@一二三对于SQL Server没有实现默认的Unicode排序规则算法规则是正确的,但是他使用代码页进行unicode排序是错误的。 https://stackoverflow.com/a/32706510/14731包含有关如何真正实现unicode排序的详细说明。