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

Why does SQL_Latin1_General_CP1_CI_AS sort number-sign before underscore?

跟进 ,我惊讶地发现:

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

根据“”,Unicode 结果应该是相反的顺序。为什么会这样?

第一件事:linked 问题 -- -- 还没有被证明是完全正确的 ;-)。

撇开这些相关信息,让我们看看各个部分:

  1. VARCHAR 字段 COLLATE SQL_Latin1_General_CP1_CI_AS:

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

    # 字符是 ASCII 代码 35,而 _ 字符是 ASCII 代码 95。这些不是字母字符,因此应该假设它们会按 # 排序首先在执行 ASC 结束订单时,就像你在这里所做的那样。

  2. NVARCHAR 字段 COLLATE SQL_Latin1_General_CP1_CI_AS:

    这将根据 Unicode 规则进行排序。 Unicode 中没有代码页,但是 可能 存在覆盖默认排序规则和排序的文化差异。并且,为了让事情变得更有趣,基本规则和 culture/locale - 特定的覆盖都可以(并且确实)多年来发生变化。软件供应商并不总是那么快速地实施新版本的标准。这与在不同时间点实现不同 W3C 规范的各种浏览器没有什么不同。 SQL Server 的主要更新随版本 2008 一起推出,该版本引入了 100 系列排序规则。 SQL Server 2012 引入了 90100 系列的变体,以 _SC 结尾,以处理增补字符(即 UCS- 2 套).

    回到刚才提到的事情,每个地区/文化都可以指定覆盖任何规则(而不仅仅是排序规则)。当前版本 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 link(从左上角开始),对于 "Punctuation",它肯定会列出“_”作为所有但一个字符。

    如果我们回溯几个版本,我们会发现(发现于: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 系列归类编码完成之后。

原来@一二三 is right about SQL Server not implementing the default Unicode Collation Algorithm rules, but he was wrong about it using a codepage for unicode sorting. 里面详细解释了unicode排序是如何真正实现的。