MySQL 提供了強大的模式匹配功能,主要包括 LIKE 和 REGEXP 兩種方式。本文將系統講解它們的語法、差異及實戰技巧。
SELECT 字段 FROM 表 WHERE 某字段 LIKE 條件
MySQL 中 LIKE 匹配預設不區分大小寫。不能使用 = 或 !=,必須使用 LIKE 或 NOT LIKE。
| 通配符 | 含義 | 範例 | 匹配結果 |
|---|---|---|---|
| % | 任意個字符(含 0 個) | LIKE '%三%' | 包含「三」的所有字符串 |
| _ | 單個字符 | LIKE '_三' | 第二個字符為「三」的字符串 |
| [範圍] | 字符集合(需配合 REGEXP) | - | - |
| [^範圍] | 非字符集合(需配合 REGEXP) | - | - |
-- 查詢用戶名包含「三」的記錄
SELECT * FROM user WHERE u_name LIKE '%三%';
-- 查詢以「張」開頭、共三個字的姓名
SELECT * FROM user WHERE u_name LIKE '張__';
LIKE '關鍵字%' 可使用索引(前綴匹配)LIKE '%關鍵字%' 會導致全表掃描,大表慎用| 元字符 | 說明 |
|---|---|
| ^ | 匹配字符串開頭 |
| $ | 匹配字符串結尾 |
| . | 匹配任意單個字符 |
| [abc] | 匹配方括號內任一字符 |
| [^abc] | 匹配非方括號內字符 |
| * | 匹配前面字符 0 次或多次 |
| + | 匹配前面字符 1 次或多次 |
SELECT * FROM m_user WHERE emp_no REGEXP '[^ -~]';
[^ -~] 匹配不在可打印 ASCII 範圍(空格到波浪號)內的字符,即可找出含中文、日文等非英文數據。
SELECT * FROM table WHERE name NOT REGEXP '[a-zA-Z0-9]+';
SELECT * FROM linkinfo
WHERE pingid REGEXP '{id},'
AND pingid NOT REGEXP '[[:alnum:]]+{id},';
FIND_IN_SET(str, strlist) 用於在逗號分隔的字符串列表中查找指定字符串的位置(從 1 開始)。
SELECT FIND_IN_SET('b', 'a,b,c,d'); -- 返回 2
注意:若第一個參數包含逗號,函數將無法正常工作。
| 場景 | 推薦方式 | 理由 |
|---|---|---|
| 簡單前綴/後綴/包含匹配 | LIKE | 語法簡單、可用索引、性能較好 |
| 複雜格式驗證(郵箱、手機號、IP) | REGEXP | 正則表達式表達力強 |
| 非 ASCII 字符檢測 | REGEXP | LIKE 無法直接表達字符範圍補集 |
| 逗號分隔字符串查找 | FIND_IN_SET | 專門優化,可用位運算加速 |
靈活運用 LIKE、REGEXP 和 FIND_IN_SET,能解決絕大多數模糊查詢需求。大數據量場景下,優先考慮 LIKE '前綴%' 利用索引,或引入全文檢索方案。