MySQL实现了几种类型的排序:
8位字符集的简单排序
这种排序是使用包含256个权重的数组实现的,该数组定义了从字符代码到权重的一对一映射。latin1_swedish_ci
是一个例子。它是一种不区分大小写的排序方式,因此一个字符的大写和小写版本具有相同的权重,并且它们在比较时是相等的。
mysql> SET NAMES 'latin1' COLLATE 'latin1_swedish_ci';mysql> SELECT HEX(WEIGHT_STRING('a')), HEX(WEIGHT_STRING('a'));+-------------------------+-------------------------+ | 十六进制(WEIGHT_STRING (' a ')) |十六进制(WEIGHT_STRING(“ ')) | +-------------------------+-------------------------+ | 41 | 41 | +-------------------------+-------------------------+ 1行组(0.01秒)mysql >选择' a ' = ' a ';+-----------+ | ' “=” ' | +-----------+ | 1 | +-----------+ 1行集(0.12秒)
有关实现说明,请参见第10.14.3节“向8位字符集添加一个简单的排序规则”。
8位字符集的复杂排序
这种排序是使用C源文件中的函数来实现的,这些函数定义了如何排序字符,如第10.13节,“添加字符集”。
非unicode多字节字符集的排序规则
对于这种类型的排序,8位(单字节)和多字节字符的处理方式不同。对于8位字符,字符代码以不区分大小写的方式映射到权重。(例如,单字节字符“一个”
和“一个”
两者的重量都是0 x41
)。对于多字节字符,字符代码和权重之间有两种关系:
权重等于字符码。
sjis_japanese_ci
是这种整理的一个例子。多字节字符“嗨!”
字符代码为0 x82c0
,重量也是0 x82c0
。mysql>创建表t1 (c1 VARCHAR(2)字符集sjis COLLATE sjis_jape_ci);mysql> INSERT INTO t1 VALUES ('a'),(' a'),(0x82C0);mysql> SELECT c1, HEX(c1), HEX(c1) (WEIGHT_STRING(c1)) FROM t1;+------+---------+------------------------+ | c1 |十六进制(c1) |十六进制(WEIGHT_STRING (c1 )) | +------+---------+------------------------+ | 41 | 61 | | | | 41 | 41 | |ぢc0 | 82 | 82 c0 | +------+---------+------------------------+ 3行集(0.00秒)
字符代码与权值一一对应,但代码不一定等于权值。
gbk_chinese_ci
是这种整理的一个例子。多字节字符'膰'
字符代码为0 x81b0
但是重量0 xc286
。mysql>创建表t1 (c1 VARCHAR(2)字符集gbk COLLATE gbk_chinese_ci);mysql> INSERT INTO t1 VALUES ('a'),(' a'),(0x81B0);mysql> SELECT c1, HEX(c1), HEX(c1) (WEIGHT_STRING(c1)) FROM t1;+------+---------+------------------------+ | c1 |十六进制(c1) |十六进制(WEIGHT_STRING (c1 )) | +------+---------+------------------------+ | 41 | 61 | | | | 41 | 41 | |膰b0 | 81 | C286 | +------+---------+------------------------+ 3行集(0.00秒)
有关实现说明,请参见第10.13节,“添加字符集”。
Unicode多字节字符集的排序规则
其中一些排序基于Unicode排序算法(UCA),另一些则不是。
非uca排序具有从字符代码到权重的一对一映射。在MySQL中,这样的排序不区分大小写和重音。utf8_general_ci
是一个例子:“一个”
,“一个”
,“一个”
,“一个”
每个都有不同的字符代码,但权重都是0 x0041
把它们相等地比较。
mysql> SET NAMES 'utf8' COLLATE 'utf8_general_ci';mysql> CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET UTF8 COLLATE utf8_general_ci);mysql> INSERT INTO t1 VALUES ('a'),(' a'),(' À'),(' ');mysql> SELECT c1, HEX(c1), HEX(c1) (WEIGHT_STRING(c1)) FROM t1;+------+---------+------------------------+ | c1 |十六进制(c1) |十六进制(WEIGHT_STRING (c1 )) | +------+---------+------------------------+ | | 61 | 0041 | | 0041 | | 41 | |的| C380 | 0041 | |是| C3A1 | 0041年 | +------+---------+------------------------+ 4行集(0.00秒)
MySQL中基于uca的排序有以下属性:
如果字符有权重,则每个权重使用2字节(16位)。
字符的权重可以为零(或者为空)。在这种情况下,字符是可忽略的。例如:“U+0000 NULL”没有权重,可以忽略。
一个角色可能有一个权重。例子:
“一个”
的权重为0 x0e33
。mysql> SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';mysql> SELECT HEX('a'), HEX('a');+----------+-------------------------+ | 十六进制(a) |十六进制(WEIGHT_STRING (' ')) | +----------+-------------------------+ | 61 | 0 e33 | +----------+-------------------------+ 1行集(0.02秒)
一个角色可能有很多权重。这是展开式。例子:德语字母
“ß”
(SZ绳,或夏普S)的重量为0 x0fea0fea
。mysql> SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';mysql> SELECT HEX('ß'), HEX('ß');+-----------+--------------------------+ | 十六进制(ß)|十六进制(WEIGHT_STRING(ß ')) | +-----------+--------------------------+ | C39F | 0 fea0fea | +-----------+--------------------------+ 1行集(0.00秒)
许多角色可能有一个权重。这是一个缩写。例子:
“ch”
在捷克语中是一个字母,重量为0 x0ee2
。mysql> SET NAMES 'utf8' COLLATE 'utf8_czech_ci';mysql> SELECT HEX('ch'), HEX('ch');+-----------+--------------------------+ | 十六进制(ch) |十六进制(WEIGHT_STRING (ch ')) | +-----------+--------------------------+ | 6368 | 0 ee2 | +-----------+--------------------------+ 1行集(0.00秒)
多字符到多权重的映射也是可能的(这是带扩展的收缩),但MySQL不支持。
有关实现说明,有关非uca排序,请参见第10.13节,“添加字符集”。有关UCA排序,请参见第10.14.4节,“向Unicode字符集添加UCA排序规则”。
各种各样的针对性
还有一些排序不属于前面的任何类别。