为何SQL Server中VARCHAR数据排序时仿佛末尾被追加了空格?
SQL Server 2017 VARCHAR排序异常:空格与纯字符串等效问题
使用SQL Server 2017时,按VARCHAR列排序出现不符合预期的结果——带制表符的字符串排在纯字符串之前,且纯字符串和末尾加任意空格的字符串表现得像等效一样。
为验证问题,执行以下SQL语句:
SELECT * FROM (VALUES (1, 'a' + CHAR(33)), (2, 'a '), (3, 'a '), (4, 'a '), (5, 'a' + CHAR(31)), (6, 'a') )v(rownum, text) ORDER BY text
预期排序结果
| rownum | text |
|---|---|
| 6 | 'a' |
| 5 | 'a(31)' |
| 4 | 'a(sp)' |
| 3 | 'a(sp)(sp)' |
| 2 | 'a(sp)(sp)(sp)' |
| 1 | 'a(33)' |
实际排序结果
| rownum | text |
|---|---|
| 5 | 'a(31)' |
| 3 | 'a(sp)(sp)' |
| 4 | 'a(sp)' |
| 2 | 'a(sp)(sp)(sp)' |
| 6 | 'a' |
| 1 | 'a(33)' |
这是因为SQL Server遵循ANSI SQL标准的字符串比较规则,在字符串相等性判断和排序时,会忽略末尾的空格。具体来说,比较两个VARCHAR字符串时,SQL Server会先把较短的字符串用空格补到和较长字符串一样的长度,再逐字符对比。这就导致'a'、'a '、'a '这类字符串在排序时被视为等效,它们的相对顺序由查询执行计划的内部逻辑(比如插入顺序、存储位置)决定。
另外,CHAR(31)是单位分隔符(US),ASCII码31小于空格的ASCII码32,所以'a' + CHAR(31)会排在所有带空格的'a'字符串以及纯'a'之前;CHAR(33)是感叹号,ASCII码大于空格,所以排在最后。
内容的提问来源于stack exchange,提问作者user221592
相关产品推荐
相关产品推荐

