當您需要查詢資料中「真正包含」百分號(%)或底線(_)時,直接使用 LIKE 會被視為通配符,導致結果錯誤。本文詳細說明轉義技巧與多種解決方案。
| 符號 | 含義 | 轉義後匹配內容 |
|---|---|---|
% | 任意長度字串 | \% 或 [%] → 字面上的 % |
_ | 單一字符 | \_ 或 [_] → 字面上的 _ |
[...] | 字符集合 | [[] → 字面上的 [ |
] | 集合結束 | ] → 字面上的 ](通常不需轉義) |
-- 查詢包含 % 的名稱
SELECT * FROM customer WHERE name LIKE '%[%]%';
-- 查詢包含 _ 的名稱
SELECT * FROM customer WHERE name LIKE '%[_]%';
-- 指定 \ 為轉義字符
SELECT * FROM customer WHERE name LIKE '%\%%' ESCAPE '\';
-- 指定 / 為轉義字符
SELECT * FROM customer WHERE name LIKE '%/%%' ESCAPE '/';
-- SQL Server
SELECT * FROM PersonalMember WHERE CHARINDEX('[', strloginname) > 0;
-- MySQL
SELECT * FROM PersonalMember WHERE LOCATE('[', strloginname) > 0;
-- 建立測試資料
CREATE TABLE PersonalMember (
id INT PRIMARY KEY AUTO_INCREMENT,
strloginname VARCHAR(50)
);
INSERT INTO PersonalMember (strloginname) VALUES
('user1'), ('test%user'), ('admin_user'), ('normal');
-- 查詢包含 % 的帳號(三種寫法皆可)
SELECT * FROM PersonalMember WHERE strloginname LIKE '%[%]%';
SELECT * FROM PersonalMember WHERE strloginname LIKE '%\%%' ESCAPE '\';
SELECT * FROM PersonalMember WHERE LOCATE('%', strloginname) > 0;
// 錯誤寫法:變數未轉義,若 $keyword 含 % 會導致錯誤結果
$sql = "SELECT * FROM customer WHERE name LIKE '%$keyword%'";
// 正確寫法 1:使用參數化查詢(推薦)
$stmt = $pdo->prepare("SELECT * FROM customer WHERE name LIKE ?");
$stmt->execute(["%$keyword%"]);
// 正確寫法 2:手動轉義特殊字符
$keyword = str_replace(['%', '_'], ['\%', '\_'], $keyword);
$sql = "SELECT * FROM customer WHERE name LIKE '%$keyword%' ESCAPE '\\'";
'\\%' 在 PHP 中代表 \% 傳給 SQL%(如 %keyword%)無法使用索引,大表建議改用全文搜尋