SQL Server中奇怪的比较结果

时间:2017-08-22 03:39:21

标签: sql-server sql-server-2008 collation sql-server-2016 codepages

  

对于没有依赖于排序规则的显式顺序的字符(即,不是大小写折叠和/或没有剥离重音符号),排序基于代码点的序数值。基本字符集。如果一个字符串是另一个字符串的前缀,则较短的字符串首先进行整理。

     

Unicode中的前128个代码点与ASCII字符集相同,这意味着/来自 - 。 ----来自cco的回答。

那为什么会发生以下情况?

Demo: How '2017/8/22 1:33:53' precedes '2017-08-13 23:12:33.411'

我预计'2017/8/22 1:33:53'将在'2017-08-13 23:12:33.411之后',因为/位于-之后。这是因为Chinese_PRC_CI_AS整理中的特殊排序吗?如果是这种情况,我在哪里可以找到规范?

3 个答案:

答案 0 :(得分:3)

  

我期待' 2017/8/22 1:33:53' ' 2017-08-13 23:12:33.411'   因为/之后 - 。这是因为特殊订购   Chinese_PRC_CI_AS整理?

是的,因为Chinese_PRC_CI_AS整理

  

如果是这种情况,我在哪里可以找到规范?

规则很复杂但你可以在这里找到它们: UNICODE COLLATION ALGORITHM

我从中提取一些文字作为图片给你一个想法: enter image description here

在您的情况下,您可以尝试使用binary归类Chinese_PRC_BIN2,它会在这种特殊情况下为您提供理想的结果,但对于字母排序来说它是不可接受的,我的意思是在欧洲语言二进制排序总是将大写字母放在所有小写字母之前,但我不知道中文符号应该如何排序

以下是使用您的订单对日期进行排序的代码(您说您使用的是UNICODE列):

declare @t table (s nvarchar(100))
insert into @t values (N'2017/8/22 1:33:53'),  (N'2017-08-13 23:12:33.411')

select *
from @t
order by s collate Chinese_PRC_BIN2;

Bin2整理将在"非unicode情况下工作"作为图片中的例子:

select case 
      when '2017/8/22 1:33:53' collate Chinese_PRC_BIN2 < 
           '2017-08-13 23:12:33.411' collate Chinese_PRC_BIN2 
      then 'TRUE' 
      else 'FALSE' 
   end;

enter image description here

答案 1 :(得分:1)

不仅仅是关于ASCII码。

是的,/的ASCII码是0x2F,-的ASCII码是0x2D,但是字符串比较规则取决于整理,这些规则可能非常复杂,不仅要考虑到字符代码。

在某些排序规则中,-符号会以特殊方式处理。

以下是一个完整的例子:

DECLARE @T1 TABLE (Value varchar(100) COLLATE Chinese_PRC_CI_AS);
DECLARE @T2 TABLE (Value varchar(100) COLLATE Latin1_General_CI_AS);
DECLARE @T3 TABLE (Value varchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS);

INSERT INTO @T1 VALUES
('abc'),
('abc-def'),
('abcdef'),
('abc-');

INSERT INTO @T2 VALUES
('abc'),
('abc-def'),
('abcdef'),
('abc-');

INSERT INTO @T3 VALUES
('abc'),
('abc-def'),
('abcdef'),
('abc-');

SELECT * FROM @T1 ORDER BY Value;
SELECT * FROM @T2 ORDER BY Value;
SELECT * FROM @T3 ORDER BY Value;

<强>结果

T1(Chinese_PRC_CI_AS)

+---------+
|  Value  |
+---------+
| abc     |
| abc-    |
| abcdef  |
| abc-def |
+---------+

T2(Latin1_General_CI_AS)

+---------+
|  Value  |
+---------+
| abc     |
| abc-    |
| abcdef  |
| abc-def |
+---------+

T3(SQL_Latin1_General_CP1_CI_AS)

+---------+
|  Value  |
+---------+
| abc     |
| abc-    |
| abc-def |
| abcdef  |
+---------+

请注意,生成的第三个表中的SQL排序规则会产生不同的顺序。

另请注意,如果将列类型更改为nvarchar,则效果会在此特定示例中消失。换句话说,处理-符号的规则取决于排序规则和值的类型。

答案 2 :(得分:0)

对于没有依赖于排序规则的显式顺序的字符(即,不是大小写折叠和/或没有剥离重音符号),排序基于代码点的序数值。基本字符集。如果一个字符串是另一个字符串的前缀,则较短的字符串首先进行整理 Unicode中的前128个代码点与ASCII字符集相同,这意味着/位于-之后。