SQL 服务器中的奇怪比较结果
Weird Comparison Result in SQL Server
For characters that are do not have an explicit order that depends on the collation (i.e., that are not case-folded and/or do not have accents stripped), the ordering is based on the ordinal value of the code point in the base character set. If one string is a prefix of another, the shorter string collates first.
The first 128 code points in Unicode are the same as the ASCII character set, which means / comes after -. ---- From cco's answer.
那为什么会出现下面的情况呢?
我希望“2017/8/22 1:33:53”出现在“2017-08-13 23:12:33.411”之后,因为 /
出现在 -
之后。这是因为 Chinese_PRC_CI_AS 排序规则中的特殊排序吗?如果是这样,我在哪里可以找到规范?
对于没有依赖于排序规则的明确顺序的字符(即,没有大小写折叠 and/or 没有去除重音符),排序基于序数值基本字符集中的代码点。如果一个字符串是另一个字符串的前缀,则较短的字符串首先进行整理。
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 (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 |
+---------+
请注意,第三个 table 中的 SQL 排序规则产生的结果顺序不同。
另请注意,如果将列类型更改为 nvarchar
,此特定示例中的效果将消失。换句话说,处理 -
符号的规则取决于排序规则和值的类型。
I expect '2017/8/22 1:33:53' to come after '2017-08-13 23:12:33.411'
because / comes after -. Is this because special ordering in
Chinese_PRC_CI_AS collation?
是的,这是因为 Chinese_PRC_CI_AS
整理
Where can I find the specification if that's the case?
规则很复杂,但你可以在这里找到它们:
UNICODE COLLATION ALGORITHM
我从中提取一些文字作为图片给你一个想法:
在您的情况下,您可以尝试使用 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 排序规则也将在 "non unicode case" 中工作,如图中的示例:
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;
For characters that are do not have an explicit order that depends on the collation (i.e., that are not case-folded and/or do not have accents stripped), the ordering is based on the ordinal value of the code point in the base character set. If one string is a prefix of another, the shorter string collates first.
The first 128 code points in Unicode are the same as the ASCII character set, which means / comes after -. ---- From cco's answer.
那为什么会出现下面的情况呢?
我希望“2017/8/22 1:33:53”出现在“2017-08-13 23:12:33.411”之后,因为 /
出现在 -
之后。这是因为 Chinese_PRC_CI_AS 排序规则中的特殊排序吗?如果是这样,我在哪里可以找到规范?
对于没有依赖于排序规则的明确顺序的字符(即,没有大小写折叠 and/or 没有去除重音符),排序基于序数值基本字符集中的代码点。如果一个字符串是另一个字符串的前缀,则较短的字符串首先进行整理。
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 (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 |
+---------+
请注意,第三个 table 中的 SQL 排序规则产生的结果顺序不同。
另请注意,如果将列类型更改为 nvarchar
,此特定示例中的效果将消失。换句话说,处理 -
符号的规则取决于排序规则和值的类型。
I expect '2017/8/22 1:33:53' to come after '2017-08-13 23:12:33.411' because / comes after -. Is this because special ordering in Chinese_PRC_CI_AS collation?
是的,这是因为 Chinese_PRC_CI_AS
整理
Where can I find the specification if that's the case?
规则很复杂,但你可以在这里找到它们: UNICODE COLLATION ALGORITHM
我从中提取一些文字作为图片给你一个想法:
在您的情况下,您可以尝试使用 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 排序规则也将在 "non unicode case" 中工作,如图中的示例:
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;