MySQL 提供兩種模糊查詢方式:LIKE(簡單模式匹配)和 REGEXP(正則表達式匹配)。選擇哪一種,取決於業務複雜度與性能要求。
| 通配符 | 含義 | 正則等價 | 示例 |
|---|---|---|---|
% | 任意長度字符(含 0 個) | .* | '%abc%' 包含 abc |
_ | 單個任意字符 | . | '_abc' 以任意字符開頭後接 abc |
-- 以 'a' 開頭
WHERE name LIKE 'a%'
-- 以 'a' 結尾
WHERE name LIKE '%a'
-- 包含 'a'
WHERE name LIKE '%a%'
-- 第二個字符是 'b'
WHERE name LIKE '_b%'
LIKE '%keyword%' 導致全表掃描,不走索引LIKE 'prefix%' 可利用 B-Tree 索引_ 匹配單字符而非單字節| 元字符 | 說明 | 示例 |
|---|---|---|
^ | 行首 | '^abc' 以 abc 開頭 |
$ | 行尾 | 'abc$' 以 abc 結尾 |
. | 任意單字符 | 'a.c' 匹配 abc、axc 等 |
* | 前項 0 次或多次 | 'ab*c' 匹配 ac、abc、abbc... |
+ | 前項 1 次或多次 | 'ab+c' 匹配 abc、abbc... |
? | 前項 0 次或 1 次 | 'ab?c' 匹配 ac、abc |
| | 或邏輯 | 'cat|dog' 匹配 cat 或 dog |
[] | 字符集合 | '[aeiou]' 匹配任意元音 |
[^] | 排除字符集 | '[^0-9]' 非數字字符 |
{n} | 精確 n 次 | 'a{3}' 匹配 aaa |
{n,m} | n 到 m 次 | 'a{2,4}' 匹配 aa、aaa、aaaa |
-- 匹配包含 a、b 或 c 的名稱
SELECT * FROM users WHERE name REGEXP 'a|b|c';
-- 匹配以字母開頭、以數字結尾
SELECT * FROM codes WHERE code REGEXP '^[A-Za-z].*[0-9]$';
-- 匹配連續兩個 b
SELECT * FROM test WHERE val REGEXP 'b{2}';
| 維度 | LIKE | REGEXP |
|---|---|---|
| 語法複雜度 | 簡單,兩個通配符 | 完整正則語法,學習成本高 |
| 索引利用 | 前綴模式可用索引 | 通常全表掃描,不走索引 |
| 執行速度 | 快(C 級實現) | 較慢(正則引擎開銷大) |
| 適用場景 | 前綴/後綴/包含匹配 | 複雜格式驗證、數據清洗 |
黃金法則: 能用LIKE解決的,絕不使用REGEXP。僅在業務邏輯必須正則時(如郵箱、手機號格式驗證、複雜文本提取)才啟用 REGEXP。
Hibernate 原生不支持 REGEXP,需通過自定義方言註冊函數:
public class MySQL5DialectRegexp extends org.hibernate.dialect.MySQLInnoDBDialect {
public MySQL5DialectRegexp() {
super();
registerFunction("regexp",
new SQLFunctionTemplate(Hibernate.BOOLEAN, "?1 REGEXP ?2"));
}
}
配置 hibernate.dialect 為該類全路徑後,HQL 即可使用:
FROM User u WHERE regexp(u.name, 'a|b|c') = 1