以数字作为字符串的排序顺序

Man*_*ngo 6 sql-server collation

出于演示目的,我有一个示例表,其中有一varchar列名为numberstring以下值:

-4
32
0
4
16
8
-8
1024
Run Code Online (Sandbox Code Playgroud)

当选择使用时ORDER BY numberstring,我发现不同的用户得到不同的结果。

有些得到:

-4, -8, 0, 1024, 16, 32, 4, 8
Run Code Online (Sandbox Code Playgroud)

而有些人得到:

0, 1024, 16, 32, -4, 4, -8, 8
Run Code Online (Sandbox Code Playgroud)

不知何故,第二个结果似乎忽略了减号,即使数据以其他方式排序为字符串数据。

据我所知,底层服务器是 Microsoft SQL Server Express 的标准安装,没有任何特殊选项。该版本是最近几年的版本,但使用相同版本的用户仍然报告不同的结果。

设置中是否有某些内容会影响结果,我如何从 SSMS 中查看它?

据我所知,数据库服务器和 SSMS 在澳大利亚设置,仅使用默认设置。数据类型是varchar(max).

Pau*_*ite 15

字符串排序顺序由排序规则决定。不同位置的用户期望数据以不同的方式排序,并且排序规则将这些期望编码化。

如果未显式指定,列的排序规则将从数据库/实例级别继承。安装 SQL Server 会设置不同的实例级排序规则,具体取决于用户选择的排序规则或从 Windows 语言设置推断的默认排序规则。从文档中:

服务器排序规则是在 SQL Server 安装期间指定的。默认服务器级排序规则基于操作系统的区域设置。

例如,使用美国英语 (en-US) 的系统的默认排序规则是SQL_Latin1_General_CP1_CI_AS。有关详细信息,包括操作系统区域设置到默认排序规则映射的列表,请参阅排序规则和 Unicode 支持的“服务器级排序规则”部分。

默认情况下,您的某些用户可能使用向后兼容的 SQL_Latin1_General_CP1_CI_AS 排序规则,而世界其他地方的其他用户可能使用类似 Latin1_General_100_CI_AS 的排序规则:

DECLARE @T table 
(
    numberstring varchar(11) COLLATE Latin1_General_100_CI_AS NOT NULL
);

INSERT @T (numberstring) VALUES
('-4'),
('32'),
('0'),
('4'),
('16'),
('8'),
('-8'),
('1024');

SELECT * FROM @T AS T ORDER BY T.numberstring;
Run Code Online (Sandbox Code Playgroud)
数字串
0
1024
16
32
4
-4
8
-8
DECLARE @T table
(
    numberstring varchar(11) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
);

INSERT @T (numberstring) VALUES
('-4'),
('32'),
('0'),
('4'),
('16'),
('8'),
('-8'),
('1024');

SELECT * FROM @T AS T ORDER BY T.numberstring;
Run Code Online (Sandbox Code Playgroud)
数字串
-4
-8
0
1024
16
32
4
8

数据库<>小提琴

出现这种情况的原因可能是您的某些用户将其 Windows 区域设置设置为英语(美国),而另一些用户将其 Windows 区域设置设置为英语(澳大利亚)

COLLATE在脚本中解决此问题的一种方法是在CREATE DATABASE语句(文档)中使用可选子句。


您可以使用以下命令查看每个数据库的默认排序规则:

SELECT D.[name], D.collation_name 
FROM sys.databases AS D
ORDER BY D.[name];
Run Code Online (Sandbox Code Playgroud)

如果返回一个NULL,则数据库可能未联机或由于AUTO_CLOSE(SQL Server Express 的默认情况ON)而关闭。请参阅的文档sys.databases

实例级排序规则:

SELECT SERVERPROPERTY('Collation');
Run Code Online (Sandbox Code Playgroud)

较旧的 SQL_* 排序规则对 Unicode 和非 Unicode 数据使用不同的规则:

SELECT FH.* 
FROM sys.fn_helpcollations() AS FH
WHERE FH.[name] IN (N'SQL_Latin1_General_CP1_CI_AS', N'Latin1_General_100_CI_AS');
Run Code Online (Sandbox Code Playgroud)
姓名 描述
Latin1_General_100_CI_AS Latin1-General-100、不区分大小写、区分重音、不区分假名类型、不区分宽度
SQL_Latin1_General_CP1_CI_AS Latin1-通用、不区分大小写、区分重音、不区分假名类型、不区分宽度(对于 Unicode 数据),对于非 Unicode 数据,代码页 1252 上的 SQL Server 排序顺序 52