前言
因测试对于中文排序提出质疑:有十个业务类型名称,排序的顺序为啥不是按照一般情况下的英文首字母排序的,如何确保每次排序都是一个顺序,故此我展开了小小的探索。
问题
数据库的数据是通过什么原则进行排序的?
- 查询语句
select brand_name,name from goods order by brand_name,name
- 结果
疑问:为何华为会排在戴尔的前面?华的拼音不是H开头,戴尔不是D开头吗?
如下将看到答案。
数据库编码方式
- gbase的中文排序是根据该数据库的编码进行排序的。可能是utf8,可能是gb2312,编码方式不同排序结果不同。(其他数据库类同)
- 通过查看表结构查看编码方式
- sql查询语句
show create table jing_dong.goods ;
- 查询结果
CREATE TABLE `goods` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(150) NOT NULL,
`cate_name` int(40) NOT NULL,
`brand_name` varchar(40) NOT NULL,
`price` decimal(10,3) DEFAULT '0.000',
`is_show` bit(1) NOT NULL DEFAULT b'1',
`is_saleoff` bit(1) NOT NULL DEFAULT b'0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8
- 解析 其中charset 就是字符集后面的 utf8 就是中文编码格式
编码地址:汉字字符集编码查询 - 华:
utf8编码 15043982 ,gbk 48042
- 戴
utf8编码: 15108276 ,gbk :46327
小结
由上可以看出,因为“华”的utf8的编码小于“戴”的所以,华为排在了戴尔的前面。
所以,如果数据库编码格式换成 gbk,那戴尔应该在华为的前面。
猜想验证
show create table jing_dong.goods ;
CREATE TABLE goods
(
id
int(10) unsigned NOT NULL AUTO_INCREMENT,
name
varchar(150) CHARACTER SET gbk COLLATE gbk_chinese_ci NOT NULL,
cate_name
int(40) NOT NULL,
brand_name
varchar(40) CHARACTER SET gbk COLLATE gbk_chinese_ci NOT NULL,
price
decimal(10,3) DEFAULT ‘0.000’,
is_show
bit(1) NOT NULL DEFAULT b’1’,
is_saleoff
bit(1) NOT NULL DEFAULT b’0’,
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=gbk
select brand_name,name from goods g order by brand_name ,name
- 排序结果
结论
由上可知,该数据的排序是基于utf8的编码进行排序的。 同时该结论对其他数据库同样适用。
插曲
只更改了最后一句的字符集编码,没有更改该字段编码格式,导致排序不符合原定猜测。如下(勿入坑):
CREATE TABLE goods
(
id
int(10) unsigned NOT NULL AUTO_INCREMENT,
name
varchar(150) CHARACTER SET utf8 NOT NULL,
cate_name
int(40) NOT NULL,
brand_name
varchar(40) CHARACTER SET utf8 NOT NULL,
price
decimal(10,3) DEFAULT ‘0.000’,
is_show
bit(1) NOT NULL DEFAULT b’1’,
is_saleoff
bit(1) NOT NULL DEFAULT b’0’,
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=gbk
select brand_name,name from goods g order by brand_name ,name
查询结果按照utf8的编码进行排序
- 结论:默认编码是该表通用规则,未标识该编码则用默认编码,若某字段有标识编码格式,则优先使用该字段的编码格式。