PHP中使用LIKE通配符%%查询MySQL数据时崩溃的问题排查
问题分析与解决办法
为啥带%的LIKE会崩溃?
核心是你PHP拼接SQL的时候引号处理错了,生成的SQL语法完全无效。你写的'" . $sourceType. "'这种写法,会让PHP把"当成普通字符串输出,最终生成的SQL里会出现" .object. "这类乱码内容,数据库根本解析不了。而你在Workbench里直接写正确的SQL,当然能正常运行。
怎么修复?
临时方案:修正字符串拼接(不建议生产环境用,有安全风险)
如果非要直接拼接字符串,得把引号和变量的关系理清楚:
$sourceType = 'object'; $sourceId = 189; $path = 'test'; // 用双引号包裹SQL,变量直接嵌入 $query = "SELECT d.targetid as id, d.sourcetype as type, CONCAT(o.o_path, o.o_key) as path FROM dependencies d INNER JOIN objects o ON o.o_id = d.targetid AND d.targettype= 'object' WHERE d.sourcetype = '$sourceType' AND d.sourceid = $sourceId AND CONCAT(o.o_path, o.o_key) LIKE '%$path%';";
或者用单引号加连接符:
$query = 'SELECT d.targetid as id, d.sourcetype as type, CONCAT(o.o_path, o.o_key) as path FROM dependencies d INNER JOIN objects o ON o.o_id = d.targetid AND d.targettype= \'object\' WHERE d.sourcetype = \'' . $sourceType . '\' AND d.sourceid = ' . $sourceId . ' AND CONCAT(o.o_path, o.o_key) LIKE \'%' . $path . '%\';';
⚠️ 注意:如果$path是用户输入的内容,这种写法会存在SQL注入风险,绝对不能在生产环境使用。
推荐方案:用预处理语句(安全还省心)
不管是PDO还是MySQLi,预处理语句都能彻底解决语法错误和安全问题:
PDO写法:
$sourceType = 'object'; $sourceId = 189; $path = 'test'; // 假设你已经完成数据库连接,$pdo是PDO实例 $stmt = $pdo->prepare(" SELECT d.targetid as id, d.sourcetype as type, CONCAT(o.o_path, o.o_key) as path FROM dependencies d INNER JOIN objects o ON o.o_id = d.targetid AND d.targettype= 'object' WHERE d.sourcetype = ? AND d.sourceid = ? AND CONCAT(o.o_path, o.o_key) LIKE ? "); // 把通配符和变量拼接好 $likePath = "%$path%"; $stmt->execute([$sourceType, $sourceId, $likePath]); // 获取查询结果 $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
MySQLi写法:
$sourceType = 'object'; $sourceId = 189; $path = 'test'; // 假设$conn是已经初始化的MySQLi连接 $stmt = $conn->prepare(" SELECT d.targetid as id, d.sourcetype as type, CONCAT(o.o_path, o.o_key) as path FROM dependencies d INNER JOIN objects o ON o.o_id = d.targetid AND d.targettype= 'object' WHERE d.sourcetype = ? AND d.sourceid = ? AND CONCAT(o.o_path, o.o_key) LIKE ? "); $likePath = "%$path%"; // 绑定参数,"sis"表示参数类型为字符串、整数、字符串 $stmt->bind_param("sis", $sourceType, $sourceId, $likePath); $stmt->execute(); $result = $stmt->get_result(); $results = $result->fetch_all(MYSQLI_ASSOC);
关于REGEXP的问题
你用REGEXP能运行但结果不全,原因有两个:
- MySQL的REGEXP默认大小写敏感(取决于数据库字符集的校对规则),比如大写的
Test可能匹配不到; - 如果
$path里包含正则特殊字符(比如.、*),会被当成正则语法解析,而非简单的字符串匹配,导致漏数据。而LIKE是纯通配符匹配,不存在这个问题。
内容的提问来源于stack exchange,提问作者Mariglen Meta
相关产品推荐
相关产品推荐

