Sql server SQL Server中奇怪的比较结果

Sql server SQL Server中奇怪的比较结果,sql-server,sql-server-2008,collation,sql-server-2016,codepages,Sql Server,Sql Server 2008,Collation,Sql Server 2016,Codepages,对于没有依赖于排序规则的显式顺序的字符(即,没有大小写折叠和/或没有去除重音),顺序基于基本字符集中代码点的序号值。如果一个字符串是另一个字符串的前缀,则较短的字符串首先进行排序 Unicode中的前128个代码点与ASCII字符集相同,这意味着/位于-根据cco的回答 那么,为什么会发生以下情况 我预计“2017/8/22 1:33:53”在“2017-08-13 23:12:33.411”之后,因为/在-之后。这是因为中国的特殊排序作为排序吗?如果是这种情况,我在哪里可以找到规范?对于没有

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

Unicode中的前128个代码点与ASCII字符集相同,这意味着/位于-根据cco的回答

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


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

对于没有依赖于排序规则的明确顺序的字符(即,没有大小写折叠和/或没有去除重音),排序基于基本字符集中代码点的顺序值。如果一个字符串是另一个字符串的前缀,则较短的字符串首先进行排序。

Unicode中的前128个代码点与ASCII字符集相同,这意味着
/
位于
-

之后。这不仅仅是关于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(中文/中华人民共和国/中华人民共和国)

T2(拉丁语1_一般_CI_AS)

T3(SQL拉丁语通用CP1 CI AS)

注意,第三个表中的SQL排序规则产生的结果顺序不同


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

我预计“2017/8/22 1:33:53”将出现在“2017-08-13 23:12:33.411”之后 因为/在…之后。这是因为在中国有特殊订单吗 中文中国词作为校勘

是的,这是因为
Chinese\u PRC\u CI\u AS
collation

如果是这样的话,我在哪里可以找到规格

规则已经够复杂了,但你可以在这里找到它们:

我从中提取一些文字作为图片,让您了解:

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

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

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;
选择案例
当“2017/8/22 1:33:53”核对中文时
“2017-08-13 23:12:33.411”整理中国的
那么“真的”
否则为“假”
终止

那么,为什么8月22日比8月13日早(在上一个示例中),正如在sql server 2016和2008上测试的那样?我对我的问题进行了编辑,以便更清楚。请查看更新版本。谢谢@出于字符串排序的目的,cco、Windows和SQL排序规则可能会对
-
符号进行不同的处理,请参见我的答案中的示例。最后要做的是比较字符串中包装的日期时间。比较之前,将这些字符串强制转换为
DATETIME
类型。更好的是,不要将日期时间存储为字符串。@TT。谢谢你的提醒!如果数据库是我做的,我当然不会这么做。。。但不管怎样,你对这个问题有什么想法(特别是为什么会出现如此奇怪的比较结果)?谢谢长度肯定会被考虑在内,这并不取决于排序规则。执行以下命令:
DECLARE@t TABLE(v NVARCHAR(3));在@t(v)值中插入('1')、('01')、('10')、('2')、('3')、('300')、('301');从@t ORDER BY v中选择*。你会看到10比2快。如果字符串的长度可能不同,或者其他字符用作分隔符,则无法比较字符串中的日期时间。请查看此问题,了解为什么字符串“2017/8/22 1:33:53”在“2017-08-13 23:12:33.411”之前。没关系,实际上是约会时间。当我们比较字符串时,前者应该在后者之后,而它不在上面的pic中。在我的例子中,列和数据类型是nvarchar。在将字符串显式转换为nvarchar后,“问题”(对我来说是一种问题,但从MS的角度来看可能是设计问题)仍然存在。可能也是因为您提到的“复杂规则”?我在哪里能找到那些规则?对不起,Ryan。我不知道在哪里可以找到排序规则的详细描述。试着问另一个具体的问题。也许有人会回答。谢谢@Vladimir。你的回答仍然非常有用!
+---------+
|  Value  |
+---------+
| abc     |
| abc-    |
| abcdef  |
| abc-def |
+---------+
+---------+
|  Value  |
+---------+
| abc     |
| abc-    |
| abc-def |
| abcdef  |
+---------+
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;
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;