首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 中文 LIKE 查詢亂碼根因與四大解決方案 (BINARY、字符集、LOCATE、COLLATE)

     編輯:MySQL 資料庫相關知識

現象重現

SET @str = '李';
SELECT * FROM users WHERE name LIKE CONCAT('%', @str, '%');
-- 結果包含非「李」字的記錄

根因剖析

  • MySQL 預設 latin1_swedish_ci / utf8_general_ci 為 不區分大小寫 (CI) 校對規則。
  • 早期版本編譯預設 latin1,中文雙位元組被拆解為單位元組比對,導致錯誤匹配。
  • LIKE 在 CI 校對下會將漢字內碼視為可轉換字元,產生誤判。

四大解決方案 (由優到劣)

1. 欄位/查詢指定 BINARY (最直接、無需改表)

-- 查詢層級
SELECT * FROM users WHERE name LIKE BINARY CONCAT('%', @str, '%');

-- 或建表指定
ALTER TABLE users MODIFY name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

原理: _bin 校對逐位元組比較,繞過語言規則。

2. 編譯/啟動指定字符集 (根治)

# 編譯時
cmake -DDEFAULT_CHARSET=utf8mb4 -DDEFAULT_COLLATION=utf8mb4_unicode_ci ..

# my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

[client]
default-character-set=utf8mb4

重啟後新建表自動繼承,舊表需 ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4。

3. 使用 LOCATE / INSTR 函數 (舊版相容)

SELECT * FROM users WHERE LOCATE(@str, name) > 0;
-- 或
SELECT * FROM users WHERE INSTR(name, @str) > 0;

函數內部逐位元組搜尋,不受校對規則影響。

4. 連線層級設定字符集 (應用端)

-- 連線後立即執行
SET NAMES utf8mb4;
-- 或 JDBC URL
jdbc:mysql://host:3306/db?characterEncoding=utf8mb4&connectionCollation=utf8mb4_unicode_ci

方案選擇矩陣

場景推薦方案備註
新專案方案 2 (utf8mb4 + unicode_ci)徹底解決、支援 Emoji
舊專案不可改表方案 1 (LIKE BINARY) 或 3 (LOCATE)零風險、效能略降
僅特定查詢需精確方案 1 (BINARY)精準控制
應用框架統一管理方案 4 (SET NAMES)集中配置

效能提示

  • BINARY / _bin 會導致全表掃描,大表建議加全文索引 (FULLTEXT) 或改用 LOCATE 配合前綴索引。
  • 5.7+ utf8mb4_unicode_520_ci / utf8mb4_0900_ai_ci 提供更準確的 Unicode 排序權重。

中文查詢亂碼本質是 字符集與校對規則不匹配,統一全鏈路 utf8mb4 是唯一長久之計。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved