
本文详解如何通过 sql `like` 运算符配合通配符(`%`)实现关键词的模糊搜索,并强调使用预处理语句防范 sql 注入,确保查询既准确又安全。
在实际开发中,用户常希望通过搜索框输入“shirt”,不仅匹配精确值 shirt,还期望返回 t-shirt、polo shirt、long-sleeve shirt 等所有包含该词的记录。但原始代码中:
$thin = $_POST['stxt']; $thing = strtoupper($thin); $sql = "SELECT * FROM products WHERE UPPER(productName) LIKE '$thing'";
存在两个关键问题:
- 缺少通配符:LIKE 'SHIRT' 等价于 = 'SHIRT',仅匹配完全一致的字符串;
- 严重安全风险:直接拼接用户输入($thing)到 SQL 语句中,极易引发 SQL 注入攻击。
✅ 正确做法是:
- 在 LIKE 比较值前后添加 % 通配符,表示“任意长度的前缀和后缀”;
- 使用 PDO 或 MySQLi 的预处理语句(Prepared Statements) 绑定参数,彻底隔离 SQL 结构与用户数据。
以下是安全、可运行的完整示例(基于 PDO):
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 2. 使用预处理语句:? 占位符 + bindParam()
$stmt = $pdo->prepare("SELECT * FROM products WHERE UPPER(productName) LIKE ?");
$stmt->bindParam(1, $pattern, PDO::PARAM_STR);
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $row) {
echo htmlspecialchars($row['productName']) . "
";
}
} catch (PDOException $e) {
error_log("SQL Error: " . $e->getMessage());
echo "搜索失败,请稍后重试。";
}
?>? 补充说明:
- %shirt% → 匹配任意位置含 “shirt” 的字符串(如 t-shirt, cotton shirt);
- shirt% → 仅匹配以 “shirt” 开头的字符串(如 shirt123, shirt-blue);
- _shirt → 下划线 _ 表示单个任意字符,如 ashirt 可匹配,但 myshirt 不匹配;
- 始终对输出内容使用 htmlspecialchars() 防止 XSS,对输入使用 trim() 和长度校验提升健壮性。
⚠️ 重要提醒:
- ❌ 绝对禁止拼接用户输入到 SQL 字符串中(如 "LIKE '$thing'");
- ✅ 必须使用预处理语句 + 参数绑定;
- ✅ 推荐将 UPPER() 移至应用层处理(如 $pattern = '%' . mb_strtoupper($thin, 'UTF-8') . '%'),避免数据库函数影响索引使用(若 productName 有索引,UPPER(productName) 将导致索引失效);如需高性能全文检索,应考虑 FULLTEXT 索引或 Elasticsearch。
掌握 LIKE '%keyword%' 与预处理的组合,是你构建安全、灵活搜索功能的基石。










