为什么 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 问题 -- -- 还没有被证明是完全正确的 ;-)。
撇开这些相关信息,让我们看看各个部分:
VARCHAR
字段 COLLATE SQL_Latin1_General_CP1_CI_AS
:
这将主要根据 ASCII 值进行排序,对于字母字符,将根据代码页 1 (a.k.a。代码页 1252) 中定义的规则进行排序和比较。
#
字符是 ASCII 代码 35,而 _
字符是 ASCII 代码 95。这些不是字母字符,因此应该假设它们会按 #
排序首先在执行 ASC
结束订单时,就像你在这里所做的那样。
NVARCHAR
字段 COLLATE SQL_Latin1_General_CP1_CI_AS
:
这将根据 Unicode 规则进行排序。 Unicode 中没有代码页,但是 可能 存在覆盖默认排序规则和排序的文化差异。并且,为了让事情变得更有趣,基本规则和 culture/locale - 特定的覆盖都可以(并且确实)多年来发生变化。软件供应商并不总是那么快速地实施新版本的标准。这与在不同时间点实现不同 W3C 规范的各种浏览器没有什么不同。 SQL Server 的主要更新随版本 2008 一起推出,该版本引入了 100
系列排序规则。 SQL Server 2012 引入了 90
和 100
系列的变体,以 _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排序是如何真正实现的。
跟进
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
根据“
第一件事:linked 问题 --
撇开这些相关信息,让我们看看各个部分:
VARCHAR
字段COLLATE SQL_Latin1_General_CP1_CI_AS
:这将主要根据 ASCII 值进行排序,对于字母字符,将根据代码页 1 (a.k.a。代码页 1252) 中定义的规则进行排序和比较。
#
字符是 ASCII 代码 35,而_
字符是 ASCII 代码 95。这些不是字母字符,因此应该假设它们会按#
排序首先在执行ASC
结束订单时,就像你在这里所做的那样。NVARCHAR
字段COLLATE SQL_Latin1_General_CP1_CI_AS
:这将根据 Unicode 规则进行排序。 Unicode 中没有代码页,但是 可能 存在覆盖默认排序规则和排序的文化差异。并且,为了让事情变得更有趣,基本规则和 culture/locale - 特定的覆盖都可以(并且确实)多年来发生变化。软件供应商并不总是那么快速地实施新版本的标准。这与在不同时间点实现不同 W3C 规范的各种浏览器没有什么不同。 SQL Server 的主要更新随版本 2008 一起推出,该版本引入了
100
系列排序规则。 SQL Server 2012 引入了90
和100
系列的变体,以_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.