為什麼 MySQL LIKE 查不到資料?連字符號與百分比的隱藏陷阱

最近我們一位客戶在網站上查詢零件資料時,遇到一個奇怪的問題。
他們輸入的關鍵字類似: Vaaon AA666-888 WEB %

照理說,資料庫裡明明就有這筆零件編號,
但當我在 MySQL 裡下指令:

SELECT * FROM parts WHERE part_number LIKE '%Vaaon AA666-888 WEB %';
  

卻完全查不到任何結果。
一開始我以為是空白或編碼問題,
結果追查下來才發現

🕵️‍♂️ 兇手竟然是那兩個不起眼的符號: %

它們在 LIKE 查詢中,其實不是普通字元,
而是被 MySQL 當成「特殊匹配符號」來處理。

% 與 _ 不是普通字元,而是「萬用字元」

在 MySQL 的 LIKE 條件查詢中,有兩個最常見的萬用符號:

符號 意義 範例 結果說明
% 代表「任意長度字元(0 個或多個)」 LIKE '%ABC%' 匹配包含「ABC」的所有字串
_ 代表「任意一個字元」 LIKE 'A_C' 匹配「AAC」、「ABC」、「ACC」等三個字元的字串

這兩個符號看似方便,但在搜尋時會造成誤判。
如果你的查詢字串裡剛好有 %_
MySQL 就會誤以為那是要當「萬用字元」使用,而不是你要查的實際內容。

那「-」又是怎麼回事?

💡 雖然 -(連字符號)在一般 LIKE 查詢中不是萬用符號,
但一旦搭配 [ ] 使用,例如: LIKE '[a-z]'
它就會變成「範圍運算符」,表示匹配 a 到 z 之間的任意字元。

這也代表,只要你的字串中剛好含有 -
又被包在某種不當的查詢邏輯中,
MySQL 可能就會誤判,導致結果不精準或完全查不到資料。

正確解法 — 用拆字匹配讓查詢更精準

知道原因後,我實際在專案中採用的方式,
將使用者輸入的關鍵字先拆開,再逐一匹配
這樣即使輸入中出現 %- 或多個空白,也不會造成查詢錯誤,
同時能保留模糊搜尋的彈性。

實際程式範例(Laravel 寫法)

// 將關鍵字拆分,每個部分都要匹配
$keywords = preg_split(‘/\s+/’, $data[‘description’]);

$query = Model::query();
foreach ($keywords as $keyword) {
    $keyword = trim($keyword);
    if (!empty($keyword)) {
        $query->where(‘description’, ‘like’, “%{$keyword}%”);
    }
}

$results = $query->get();

這樣的查詢邏輯有三個好處:

  • 避免誤判特殊字元:即使輸入中有 %-_ 等符號,MySQL 仍會當作普通字元處理。
  • 可搜尋多組關鍵字:使用者輸入「Vaaon AA666-888 WEB %」時,系統會分別比對「Vaaon」、「AA666-888」、「WEB」、「%」,讓搜尋更寬鬆、容錯性更高。
  • 方便擴充條件:若未來要支援多欄位查詢(例如 part_numberdescriptionmodel),只要在 foreach 內新增 orWhere() 即可延伸。

原本不是我的專案,卻讓我意外發現新天地

這個專案原本並不是我負責開發的,當初只是臨時協助客戶處理搜尋異常的問題。
一開始我也一頭霧水——系統本身沒有報錯,資料也在,但輸入關鍵字 Vaaon AA666-888 WEB % 卻完全查不到。

直到我深入看程式邏輯、實際測試 LIKE 查詢,才發現這類符號在 MySQL 裡竟然會被誤判成「特殊匹配字元」。也因為這次的經驗,我才真正理解到:
搜尋邏輯不只是技術問題,而是一種對使用情境的理解。最後我改用「關鍵字拆分匹配法」,
讓系統能自動判斷並逐一搜尋多段內容,不只解決了客戶的需求,也讓我學到更通用、更彈性的查詢思維。

這段過程雖然只是小小的除錯任務,但卻讓我重新定義「模糊搜尋」的真正意義
不是模糊查資料,而是讓搜尋更懂人。

常見問題 FAQ

💬 你有其他的經驗想和我分享嗎?

或者你也曾遇過這種查不到卻又不是 bug 的情況?
歡迎留言聊聊,也許你的案例能讓更多人少踩幾個坑。

我要留言分享觀點

返回頂端