前言
之前一篇文章讲了排序规则的基本概念和误区。今天的文章我主要针对论坛里面一个朋友问他问题,深入的讲下排序规则。这些东西是我感觉我查了很多资料和博客都没有讲到的内容。本文尽量通过自己的理解,使用通俗易懂的语言来讲解。希望能够帮助大家更加深入的了解他的工作原理.
案例
SELECT * FROM (
SELECT '-' AS t
UNION
SELECT '1' AS t
) A
ORDER BY A.t
COLLATE Chinese_PRC_CI_AS
SELECT * FROM (
SELECT '-11' AS t
UNION
SELECT '11' AS t
) A
ORDER BY A.t
COLLATE Chinese_PRC_CI_AS
执行结果截图如下:
为什么这2个查询结果会是上面的这个结果呢。-和1怎么比较。11为什么比-11还小?看起来这个结果
分析
通过之前的文章我们知道,Chinese_PRC_CI_AS 是我们在中国地区默认的排序规则。表示支持的*的 不区分大小写,区分重音的字符集。这是我们最常用的排序规则之一。首先上面的案例中,是对字符串进行排序,而不是对应的阿拉伯数字进行排序。那么他需要按照对应的排序规则来对字符串进行排序。Chinese_PRC_CI_AS 使用的是windows排序规则。它对应的代码页是936.
代码页
在之前我也一直很疑惑,什么是代码页,排序规则和代码页有什么关系,和字符集(GBK,UTF8等)又有什么联系和区别。其实,代码页也称为“内码表”,是与特定语言的字符集相对应的一张表。操作系统中不同的语言和区域设置可能使用不同的代码页.代码页和字符集是对应的。但是代码页一般与其所直接对应的字符集之间并非完全等同,往往因为种种原因(比如标准跟不上现实实践的需要)而会对字符集有所扩展。代码页的指定在Windows中是系统默认设置的(即默认系统区域设置),也可在(Windows7的)“控制面板-区域和语言-管理-非Unicode程序的语言-更改系统区域设置”中选择列表中的语言进行更改。
字符集和字符编码
ANSI是美国国家标准学会(American National Standards Institute)的缩写。ANSI这个组织做了很多标准制定工作,包括C语言规范ANSI C,还有各国字符编码对应的“代码页(code page)”标准。,ANSI规定简体中文GB编码的代码页是936,所以GB编码又叫做ANSI code page 936(ANSI标准的代码页936).在Windows系统的编码处理中,ANSI编码一般代表系统默认编码方式,而且并不是确定的某一种编码方式——在简体中文操作系统中ANSI编码默认指的是GB系列编码(GB2312、GBK、GB18030)GBK编码表现在我们回到最初的案例,‘-‘’为什么排在‘1‘前面。查看GBK的编码表就可以一眼看出来,-号是放在‘1’前面。当然对应转换后的16进制或者10进制,‘-’对应的10进制是45 ‘1’对应的10进制是49.
而对于第二个查询就涉及多个字符的排序。他们把这些字符对应的10进制加起来进行比对。然后排序 -11 对应的十进制分别是45 49 49 而11对应的是49 49 ,所以11是小于-11的,自然11就排在-11前面。
总结
排序规则Chinese_PRC_CI_AS使用的是GBK编码。通过查看这个编码的规则,我们就可以找到上面SQL排序的原理。 如果我们需要按照阿拉伯数字来 ,可以先把字符串转换为数字,例如:SELECT * FROM (
SELECT '-11' AS t
UNION
SELECT '11' AS t
) A
ORDER BY cast(A.t as int)