業務場景:用戶登錄、賬號創建、角色命名需嚴格區分大小寫,但 MySQL 預設校對規則(如 utf8_general_ci)為不區分大小寫(Case Insensitive)。本文對比三類解決方案,推薦「修改 SQL/存儲過程 + BINARY 操作符」的低風險、零改架構方案,並附驗證實測。
| 方案 | 操作層面 | 風險 | 適用性 |
|---|---|---|---|
修改實例級參數 lower_case_table_names / 字符集 | 服務器配置 | 極高:影響所有庫表、可能導致現有數據亂碼、重啟生效 | 新建實例、無歷史數據 |
修改庫/表/列字符集與校對規則(如 utf8_bin) | Schema 結構 | 中:需重建表/轉換數據、影響現有索引與排序 | 局部表需區分大小寫 |
SQL/存儲過程中使用 BINARY 操作符 | 查詢語句 | 極低:不動結構、不改配置、精準控制範圍 | 存量系統、少量業務點需區分 |
BINARY 非函數,而是類型轉換操作符,強制其後字符串按二進制字節比較,從而實現區分大小寫:
mysql> SELECT BINARY 'ABCD' = 'abcd' AS ret1, 'ABCD' = 'abcd' AS ret2;
+------+------+
| ret1 | ret2 |
+------+------+
| 0 | 1 |
+------+------+
ret1=0:BINARY 生效,'ABCD' ≠ 'abcd'(區分大小寫)。ret2=1:默認校對規則,'ABCD' = 'abcd'(不區分大小寫)。CREATE PROCEDURE sp_login(IN p_user VARCHAR(50), IN p_pass VARCHAR(100))
BEGIN
SELECT uid, username FROM users
WHERE username = BINARY p_user -- 賬號區分大小寫
AND password = BINARY p_pass; -- 密碼區分大小寫
END;
-- 檢查用戶名是否存在(區分大小寫)
SELECT COUNT(*) FROM users WHERE username = BINARY 'Admin';
-- 唯一索引輔助:若業務全量需區分,建表時指定列校對規則
CREATE TABLE users (
username VARCHAR(50) COLLATE utf8_bin UNIQUE -- 列級指定二進制校對
);
SET @sql = CONCAT('SELECT * FROM ', @tbl, ' WHERE code = BINARY ', QUOTE(@code));
PREPARE stmt FROM @sql; EXECUTE stmt;
WHERE col = BINARY 'val' 可能導致列索引失效(隱式轉換),若該列頻繁查詢且數據量大,建議改用列級 COLLATE utf8_bin 或功能性索引(MySQL 8.0+)。SET NAMES utf8mb4)與表一致,避免雙重編碼轉換導致比較異常。utf8mb4_bin、latin1_bin 同理,推薦統一用 utf8mb4_bin 支持完整 Unicode。對於存量系統中少數業務需區分大小寫,**在 SQL/存儲過程中針對性加 BINARY 是風險最小、見效最快**的方案。若業務全域需區分,建議庫/表/列級統一指定 _bin 校對規則,從源頭解決。