在此示例中,MSSQL 中字符的 ORDER BY 如何工作?

How is ORDER BY of chars in MSSQL working in this example?

我正在尝试了解 order by 的工作原理。在书中 SQL Heads down 作者提到大写字母在选择和排序时应该出现在小写字符“之前”。

为什么字母不按顺序显示: AaBbCcDd 而不是 AabBCcdD?

值得注意的是,作者在MySQL中给出了示例,而我使用的是MSSQL。

您应该检查一下您的数据库中的 collation order:看起来当前的数据库只是将同一字符的大写和小写版本视为无法区分,因此它们将以任何顺序结束。

这就是为非英语用法开发系统如此可爱的任务的原因:很少有西欧语言同意正确的字母顺序排列方式!众所周知,ÅÄÖ排在最后,而V和W在排序时难以区分...

In the book SQL Heads down the author mentions that Uppercase letters should show up "before" lowercase characters whilst selecting and ordering them.

这种说法充其量只是部分正确,实际上是错误的。字符的“排序”顺序与值所在的排序规则以及当它们相等时如何处理这些值有关。采取以下措施:

CREATE TABLE dbo.SomeTable (ID int IDENTITY PRIMARY KEY CLUSTERED, --Gives the RDBMS something else it is likely to ORDER BY, but NOT guarenteed
                            Insensitive char(1) COLLATE Latin1_General_CI_AI,
                            CaseSensitive AS Insensitive COLLATE Latin1_General_CS_AI,
                            AccentSensitive AS Insensitive COLLATE Latin1_General_CI_AS,
                            CaseAndAccentSensitive AS Insensitive COLLATE Latin1_General_CS_AS,
                            BinaryCollation AS Insensitive COLLATE Latin1_General_BIN,
                            SQLLatin AS Insensitive COLLATE SQL_Latin1_General_CP1_CI_AI);

GO


INSERT INTO dbo.SomeTable
VALUES('a'),('A'),('b'),('B'),('C'),('c'),('D'),('d'),('e'),('E');
GO

SELECT ID,Insensitive
FROM dbo.SomeTable
ORDER BY Insensitive;
GO

SELECT ID,CaseSensitive
FROM dbo.SomeTable
ORDER BY CaseSensitive;
GO

SELECT ID,AccentSensitive
FROM dbo.SomeTable
ORDER BY AccentSensitive;
GO

SELECT ID,CaseAndAccentSensitive
FROM dbo.SomeTable
ORDER BY CaseAndAccentSensitive;
GO

SELECT ID,BinaryCollation
FROM dbo.SomeTable
ORDER BY BinaryCollation;
GO

SELECT ID,SQLLatin
FROM dbo.SomeTable
ORDER BY SQLLatin;
GO

DROP TABLE dbo.SomeTable;

在上面,我们得到了几个不同的命令。首先,使用排序规则 Latin1_General_CI_AIInsensitive 排序,我们得到与您类似的订单。我将 ID 包含在 SELECT 中,因为这可能意味着对于如此小的数据集,数据将按 CLUSTERED INDEX.

的顺序返回

接下来,Latin1_General_CS_AI,数据按小写,大写顺序返回。 Latin1_General_CI_AS returns 与 Insensitive 顺序相同,CaseAndAccentSensitiveLatin1_General_CS_AI.

顺序相同

然后我们有二进制排序规则。对于我选择的Latin1_General_BIN,顺序是所有大写字符在前,然后是所有小写字符。

然后,最后,我们有 SQL_Latin1_General_CP1_CI_AI 符合您对先大写再小写的期望。