我遇到了'order by'与varchar与nvarchar数据的结果之间的意外差异。在这两种情况下,有问题的数据来自旧的ASCII字符集;在以nnn vs -nnn开头的订货数据中出现差异,其中n是数字。SQL Server意外'order by'区别varchar与nvarchar
下面是重现问题的SQL Server脚本;我的测试服务器是SQL 2016,但我在2008年和2012年也重现了这个问题。我尝试了不同的排序规则,但没有任何效果(除Latin1_General_bin外,请参见下文)。该脚本创建了2个类似于我们应用程序中的示例表,其中一个使用varchar和另一个nvarchar,并添加了7行数据。
CREATE TABLE [dbo].[_ValidationLists](
[_FldNum] [int] NOT NULL,
[_ValidationEntry] [varchar](250) NOT NULL,
CONSTRAINT [PK__ValidationLists] PRIMARY KEY CLUSTERED
(
[_ValidationEntry] ASC,
[_FldNum] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[_ValidationListsN](
[_FldNum] [int] NOT NULL,
[_ValidationEntry] [nvarchar](250) NOT NULL,
CONSTRAINT [PK__ValidationListsN] PRIMARY KEY CLUSTERED
(
[_ValidationEntry] ASC,
[_FldNum] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT INTO [_ValidationLists] (_fldnum, _ValidationEntry) VALUES (1,'-1'), (1,'-10'), (1,'-100'), (1,'0'), (1,'1'), (1,'10'), (1,'100')
INSERT INTO [_ValidationListsN] (_fldnum, _ValidationEntry) VALUES (1,N'-1'), (1,N'-10'), (1,N'-100'), (1,N'0'), (1,N'1'), (1,N'10'), (1,N'100')
select * from [_ValidationLists]
order by [_ValidationEntry] asc
select * from [_ValidationListsN]
order by [_ValidationEntry] asc
select语句的结果如下。第一个结果,varchar,就是我所期望的(词典排序);第二个结果我无法解释。首先是我们的客户群也期望得到,我们被这个结果吓到了。 (客户数据不常见 - 通常此表用于alpha数据;而alpha数据对于varchar和nvarchar都有相同的顺序)。
使用N'...'来初始化_ValidationListsN行的结果是相同的。原始数据的条目较长,如'-100:Pass';我已经编辑了数据,至少证明了这个问题。
用空格填充所以所有条目都是相同的长度没有影响。
使用COLLATE Latin1_General_bin重现了词典排序,但是不可接受,因为(仅出于一个原因)我们通常使用不区分大小写的排序。
我们报告这个问题的客户只有ASCII数据,所以我们可以通过使用varchar重新创建这个表来修复它们。我很想知道为什么nvarchar的行为是这样的,因为结果对我来说似乎不正确,并且如果有办法获得我们期望的排序行为(第一种情况)。至少我不知道为什么所有以' - '开头的条目(ASCII 0X2d,短划线或负号)不一起排列。
_FldNum _ValidationEntry
1 -1
1 -10
1 -100
1 0
1 1
1 10
1 100
(7行(S)的影响)
_FldNum _ValidationEntry
1 0
1 1
1 -1
1 10
1 -10
1 100
1 -100
(受影响的7行(S))
如果数据是数字,为什么不使用数字数据类型? – HLGEM
数据通常是alphnumeric - 在实际的客户数据条目中,例如,'-123:Pass'。我已经将数据归结到了显示效果的最小值。 – RFaneuf