現象:WHERE title LIKE '%a%' 返回大量不含「a」的中文記錄。根因:非二進制排序規則下,多字節中文字符的某些字節值與 ASCII 字母重疊,導致誤匹配。本文提供標準化解決方案,兼顧大小寫不敏感與精確匹配。
utf8mb4_general_ci)為**不區分大小寫、按字符集權重比較**LIKE '%a%' 在字節層面匹配,非字符層面 → 中文內碼字節命中「a」SELECT id, title, name FROM news
WHERE BINARY title LIKE '%a%';
效果:消除中文誤匹配。
副作用:區分大小寫,「Achech」≠「achech」。
SELECT id, title, name FROM news
WHERE BINARY UCASE(title) LIKE '%A%';
效果:標題與關鍵字同轉大寫,實現不區分大小寫精確匹配。
-- 應用層傳入關鍵字變數 @keyword
SELECT id, title, name FROM news
WHERE BINARY UCASE(title) LIKE CONCAT('%', UCASE(@keyword), '%');
優勢:
• 應用層只需傳入原始關鍵字,無需手動加 %
• 關鍵字同樣經 UCASE,大小寫完全中和
• 防注入:參數化查詢中 @keyword 作為值傳遞,非 SQL 拼接
<?php
$keyword = $_GET['q'] ?? '';
$stmt = $conn->prepare("
SELECT id, title, name FROM news
WHERE BINARY UCASE(title) LIKE CONCAT('%', UCASE(?), '%')
");
$stmt->bind_param("s", $keyword);
$stmt->execute();
$result = $stmt->get_result();
// ...
?>
WHERE BINARY UCASE(title) LIKE UCASE(CONCAT('%', ?, '%'))
效果相同,UCASE 包裹整個模式串。
| 方案 | 索引使用 | 效能 | 適用場景 |
|---|---|---|---|
LIKE 'abc%' (前綴) | 可用索引 Range Scan | 快 | 前綴搜尋 |
LIKE '%abc%' (中綴/後綴) | **全表掃描** | 慢 | 任意位置搜尋 |
BINARY UCASE(...) LIKE ... | **全表掃描** + 函數計算開銷 | 較慢 (N ms) | 精確中英文混合搜尋 |
全文索引 MATCH() AGAINST() | 全文索引 | 極快 | 自然語言、長文本搜尋 |