
本文详解如何正确使用 sql 的 like 操作符配合通配符(% 和 _)实现模糊搜索,并强调通过预处理语句防范 sql 注入,确保查询既准确又安全。
在实际开发中,用户常希望通过关键词(如 “shirt”)检索出所有相关产品名称,例如 shirt、t-shirt、polo shirt 或 shirt dress。但若直接使用 LIKE '$thing'(无通配符),SQL 仅执行精确匹配,等价于 = '$thing',因此只会返回完全等于 SHIRT 的记录,无法满足“包含”语义。
✅ 正确用法:通配符 % 是关键
LIKE 操作符需配合通配符才能实现子串匹配:
- % 表示零个、一个或多个任意字符;
- _ 表示恰好一个任意字符(较少用于全文模糊搜索)。
要查找 productName 中任意位置包含 $thin(不区分大小写)的记录,应将通配符置于变量两侧:
$thin = $_POST['stxt'] ?? ''; // 推荐:先清理输入,再转换为大写(或统一小写),保持逻辑一致 $thing = strtoupper(trim($thin)); // ❌ 错误:无通配符 → 精确匹配 // $sql = "SELECT * FROM products WHERE UPPER(productName) LIKE '$thing'"; // ✅ 正确:前后加 % → 模糊匹配(包含) $sql = "SELECT * FROM products WHERE UPPER(productName) LIKE '%" . $thing . "%'";
但上述拼接方式仍存在严重风险——SQL 注入漏洞。例如,若用户输入 shirt' OR '1'='1,将导致非法查询执行。
? 安全实践:必须使用预处理语句(Prepared Statements)
推荐使用 PDO 或 MySQLi 的参数化查询,彻底隔离 SQL 结构与用户数据:
✅ PDO 示例(推荐):
$thin = $_POST['stxt'] ?? '';
$thing = strtoupper(trim($thin));
try {
$pdo = new PDO("mysql:host=localhost;dbname=your_db", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare("SELECT * FROM products WHERE UPPER(productName) LIKE ?");
$searchPattern = "%{$thing}%"; // 通配符在 PHP 层拼接,更安全可控
$stmt->execute([$searchPattern]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $row) {
echo htmlspecialchars($row['productName']) . "
";
}
} catch (PDOException $e) {
error_log("Query failed: " . $e->getMessage());
}✅ MySQLi 面向对象示例:
$thin = $_POST['stxt'] ?? '';
$thing = strtoupper(trim($thin));
$stmt = $mysqli->prepare("SELECT * FROM products WHERE UPPER(productName) LIKE ?");
$searchPattern = "%{$thing}%";
$stmt->bind_param("s", $searchPattern);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo htmlspecialchars($row['productName']) . "
";
}⚠️ 注意事项与最佳实践
- 永远不要拼接用户输入到 SQL 字符串中 —— 即使已 strtoupper() 或 trim(),也无法阻止注入;
-
通配符位置决定匹配逻辑:
- '%shirt' → 以 shirt 结尾;
- 'shirt%' → 以 shirt 开头;
- '%shirt%' → 包含 shirt(最常用);
- 性能提示:LIKE '%value%' 无法有效利用普通 B-Tree 索引,若数据量大,可考虑添加函数索引(MySQL 8.0+)或全文索引(FULLTEXT)提升效率;
-
大小写处理建议:使用 COLLATE utf8mb4_general_ci(或类似不区分大小写的校对规则)替代 UPPER() 函数,既简化 SQL,又利于索引使用:
SELECT * FROM products WHERE productName LIKE ? COLLATE utf8mb4_general_ci;
掌握 LIKE '%...%' 的语义与预处理机制,是构建健壮、安全、可维护搜索功能的基础。务必在每一次涉及用户输入的查询中贯彻该原则。










