MySQL中文拼音排序的問題與解決方案
問題
在做通訊錄、人員列表等功能時,經(jīng)常會碰到按照中文拼音排序的問題。
我們在這里可以用一個簡單的例子進行說明
先創(chuàng)建測試數(shù)據(jù)
CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
INSERT INTO user (name) VALUES
('張三'),('李四'),('王五'),('趙六'),('錢七'),('孫八'),('周九'),('吳十');
下面,我們希望查出數(shù)據(jù),并且按照中文拼音順序排序
很簡單,這樣就行了
SELECT * FROM user ORDER BY name;
可是,執(zhí)行后卻發(fā)現(xiàn),結(jié)果似乎并不符合預期

這其實是因為,MySQL 默認字符集排序:
utf8mb4_general_ciutf8mb4_unicode_ci
這些排序是 按 Unicode 編碼點排序,而不是拼音順序。
那么,我怎么實現(xiàn)中文拼音排序呢?
解決辦法
方法一
默認字符集排序不支持,那我不用默認字符集不就行了,看我的
SELECT * FROM user ORDER BY CONVERT(NAME USING gbk);

如果在 xml 里面使用,注意使用CDATA包裹
<select id="listUsers" resultType="User"> SELECT id, name FROM user ORDER BY <![CDATA[CONVERT(name USING gbk)]]> </select>
可行是可行,但是每次查詢都要做編碼轉(zhuǎn)化,有沒有更簡單粗暴的方法?
方法二
有的兄弟,有的
我們可以跳過編碼轉(zhuǎn)化這一個步驟,添加一個冗余字段,在數(shù)據(jù)變更時寫入拼音不就行了(空間換時間打法還是太強了)
我們先添加字段
ALTER TABLE user ADD COLUMN pinyin VARCHAR(100) AFTER name;
再導入這樣一個依賴
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.1</version>
</dependency>
再建立對應工具類
public class PinyinUtil {
/**
* @param chinaStr 中文字符串
* @return 中文字符串轉(zhuǎn)拼音 其它字符不變
*/
public static String getPinyin(String chinaStr){
HanyuPinyinOutputFormat formart = new HanyuPinyinOutputFormat();
formart.setCaseType(HanyuPinyinCaseType.LOWERCASE);
formart.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
formart.setVCharType(HanyuPinyinVCharType.WITH_V);
char[] arrays = chinaStr.trim().toCharArray();
String result = "";
try {
for (int i=0;i<arrays.length;i++) {
char ti = arrays[i];
if(Character.toString(ti).matches("[\u4e00-\u9fa5]")){ //匹配是否是中文
String[] temp = PinyinHelper.toHanyuPinyinStringArray(ti,formart);
result += temp[0];
}else{
result += ti;
}
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
return result;
}
}
PinyinUtil.getPinyin()會根據(jù)中文字符串返回對應的拼音字符串
在涉及到數(shù)據(jù)變更(新增、修改、導入等場景)時,寫入冗余字段就行
String pinyin = PinyinUtil.getPinyin(name); user.setPinyin(pinyin);
我們的測試數(shù)據(jù)表在經(jīng)過處理后,就變成了這樣

查詢時,對冗余字段排序即可
SELECT * FROM user ORDER BY pinyin;

當數(shù)據(jù)量超過 幾百萬條以上,方法二的優(yōu)勢會明顯
當然,方法一不用做多余操作,直接sql搞定,也是一個優(yōu)點
到此這篇關(guān)于MySQL中文拼音排序的問題與解決方案的文章就介紹到這了,更多相關(guān)MySQL中文拼音排序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL事務(wù)及Spring隔離級別實現(xiàn)原理詳解
這篇文章主要介紹了MySQL事務(wù)及Spring隔離級別實現(xiàn)原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-05-05

