MySQL 8.0.26+ 支持 utf8mb4_pinyin_ci 校对规则,可按标准普通话拼音排序并处理多音字;旧版中 CONVERT(col USING gbk) 取首字节实现首字母排序属误用,因 GBK 首字节与拼音无关,真正决定排序的是 collation 规则。

MySQL 中直接用 CONVERT 做拼音首字母排序行不通
想靠 CONVERT(col USING gbk) 或 CONVERT(col USING gb2312) 把中文转成 GBK 编码,再取首字节当拼音首字母——这招在旧版 MySQL(如 5.5)里看似能“碰巧”跑通,但本质是误用。GBK 编码中汉字的首字节范围是 0x81–0xFE,和拼音字母完全无关;真正决定“首字母顺序”的是字符的 collation 排序规则,不是编码字节值。
真正起作用的是 utf8mb4_unicode_ci 或 utf8mb4_pinyin_ci(MySQL 8.0+)
MySQL 8.0.26 起官方支持 utf8mb4_pinyin_ci collation,它会按汉字标准普通话拼音排序,且自动处理多音字(按常用读音)、忽略标点与空格。启用方式很简单:
SELECT name FROM users ORDER BY name COLLATE utf8mb4_pinyin_ci;
如果你用的是 MySQL 5.7 或 8.0 早期版本(Unknown collation: 'utf8mb4_pinyin_ci'。此时别硬套 CONVERT,得换路子。
兼容老版本的实操方案:用 ELT + LOCATE 模拟首字母映射
核心思路是建一张「汉字→首字母」映射表(或用 CASE/ELT 内联),对字段首字符查表取字母,再排序。注意三点:
- 必须先用
SUBSTRING(col, 1, 1)提取首字符,不能用LEFT(col, 1)(在某些 collation 下可能截断半个 UTF-8 字符) - 映射表要覆盖常用汉字,建议用《GB2312 一级汉字》前 3755 字,按拼音首字母分组整理(如“阿啊”→A、“八芭”→B)
- 性能差:每次排序都要执行字符串匹配,千万级表慎用;务必给该字段加函数索引(MySQL 8.0+):
CREATE INDEX idx_name_first ON users ((SUBSTRING(name, 1, 1)));
简易内联写法(仅示意前几个字):
ORDER BY ELT(LOCATE(SUBSTRING(name,1,1), '阿八嚓哒妸发噶哈吉咖拉妈拿哦啪期然仨他哇吓丫匝'), 'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','W','X','Y','Z')
为什么不用 SUBSTRING_INDEX + convert + hex?
网上有些方案让先 CONVERT(SUBSTRING(col,1,1) USING gbk),再 HEX() 取高位字节,再手动映射 0xB0–0xB9 → A–J……这类做法错误根源在于:GBK 区位码 ≠ 拼音顺序,比如“赵”(0xD5,0xC4)、“钱”(0xC7,0xAE)、“孙”(0xCB,0xEF)的首字节分别是 0xD5、0xC7、0xCB,数值顺序是钱→孙→赵,但拼音是 Q→S→Z,完全对不上。用字节硬凑,排序结果必然错乱。
真正稳定的做法只有两个:升级到 MySQL 8.0.26+ 用原生 utf8mb4_pinyin_ci,或老版本接受性能代价走映射表。别在 CONVERT 上浪费调试时间——它解决不了拼音排序问题。











