中文字段排序(MySQL与PostgreSQL)
在MySQL(5.5.8)与PostgreSQL(9.0)中建立相同的测试表、数据:
create table test_gbk_char(
id int,
username varchar(64)
);
insert into test_gbk_char values(1,'青霞'),(2,'曼玉'),(3,'楚红');
id int,
username varchar(64)
);
insert into test_gbk_char values(1,'青霞'),(2,'曼玉'),(3,'楚红');
上述步骤完成之后,检查两者之间的字符集及其校验规则:
MySQL(在建表时我没有指定其校验规则及使用默认校验规则):
+--------------------------+-------------------------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
----------------------------------------------------------------------------------------
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
PostgreSQL:
ENCODING = 'UTF8'
TABLESPACE = pg_default
LC_COLLATE = 'Chinese (Simplified), Singapore'
TABLESPACE = pg_default
LC_COLLATE = 'Chinese (Simplified), Singapore'
LC_CTYPE ='Chinese (Simplified), Singapore'
排序查询:
MySQL:
select * from test_gbk_char order by username;
2 曼玉
3 楚红
1 青霞
PostgreSQL:
select * from test_gbk_char order by username;
3;"楚红"
2;"曼玉"
1;"青霞"
从上面的结果可以看出PostgreSQL给出的结果是我想要的。那么造成这种差异的原因是什么呢?其实上文已经给出答案。主要是因为校验规则的不同。
utf8默认的校验规则是utf8_general_ci,它不会按照中文进行排序。如果想要mysql中的结果与PostgreSQL中的结果一样,有多种方法,比如修改表、字段字符集校验规则定义,如果不想修改表结构,可以在查询时进行转换:
select * from test_gbk_char order by CONVERT(username USING gbk) COLLATE gbk_chinese_ci;
3 楚红
2 曼玉
1 青霞
注:以上的对比查询只是为了说明不同字符校验对中文字段的影响,并不是说mysql与postgreSQL的排序异同。
参考: