首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL LIKE 查詢中下劃線 (_) 被當作通配符的陷阱與解決方案

     編輯:MySQL 資料庫相關知識

問題現象

用戶在搜索框輸入 ___、.__ 等包含下劃線的關鍵字時,返回了數據表中的所有記錄。

根本原因

MySQL LIKE 模式匹配中,兩個通配符:

符號含義
%匹配任意長度字符(含 0 個)
_匹配任意單個字符

___ 即匹配任意 3 個字符的字符串,.__ 匹配任意 3 個字符(第一個任意字符 + 兩個下劃線),導致幾乎所有記錄命中。

官方文檔確認

MySQL String Comparison Functions 明確定義 _ 為單字符通配符。

解決方案:轉義用戶輸入

PHP 方案

$keyword = $_POST['keyword'];
// 轉義 % 和 _
$keyword = str_replace(['%', '_'], ['\\%', '\\_'], $keyword);
$sql = "SELECT * FROM products WHERE name LIKE '%{$keyword}%'";

Java 方案

String keyword = request.getParameter("keyword");
keyword = keyword.replace("%", "\\%").replace("_", "\\_");
String sql = "SELECT * FROM products WHERE name LIKE ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "%" + keyword + "%");

MySQL 原生轉義

SELECT * FROM products WHERE name LIKE '%\_\_\_%' ESCAPE '\\';
-- 指定反斜槓為轉義字符

影響範圍調查

經驗證,早期流行的 PHP 論壇程序 IPB、phpBB 均存在此漏洞;vBulletin 已內置過濾。建議所有使用 LIKE 的應用審查用戶輸入處理邏輯。

最佳實踐建議

  1. 統一入口過濾:在框架/公共庫層封裝 escapeLikeWildcards() 方法
  2. 參數化查詢:使用 PreparedStatement,雖然不自動轉義通配符,但可配合手動轉義
  3. 全文搜索替代:大數據量場景改用 MySQL Fulltext 或 Elasticsearch,避免 LIKE %...% 全表掃描
  4. 單元測試:添加包含 %、_ 的測試用例

其他數據庫對比

數據庫單字符通配符轉義語法
MySQL_\_ 或 ESCAPE '\'
PostgreSQL_\_ 或 ESCAPE '\'
SQL Server_[_] 或 ESCAPE '\'
Oracle_ESCAPE '\'
SQLite_ESCAPE '\'

幾乎所有主流關係型數據庫均遵循 SQL 標準,_ 為單字符通配符,開發時務必注意。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved