PHP PDO多SELECT查询失效求助:筛选特定条件玩家数据
排查PDO执行多条SELECT查询异常的问题
嘿,我来帮你搞定这个PDO查询的问题!先说说你遇到的问题根源,再给你两种可行的解决方案。
问题原因
- PDO默认禁用多语句执行:为了防范SQL注入风险,PDO默认关闭了
PDO::MYSQL_ATTR_MULTI_STATEMENTS属性,直接在一个SQL字符串里写两个SELECT语句(哪怕加分号分隔),都会触发异常。 - 结果集处理逻辑错误:就算你开启了多语句支持,用
query()执行后,默认只能获取第一个查询的结果集,你的代码里直接用while ($dnn = $q->fetch())只会遍历第一个查询的结果,第二个结果集根本拿不到。
解决方案1:用UNION合并查询(优先推荐)
把两个查询合并成一条SQL语句,这是最简洁高效的方式,不需要修改PDO的安全设置,代码也更容易维护:
// 合并两个查询,确保返回的字段一致(这里查同一张表的*,所以没问题) $sql = "SELECT * FROM allplayers WHERE points > 0 UNION SELECT * FROM allplayers WHERE points = 0 AND qualified > 0 ORDER BY points DESC"; $q = $pdo->query($sql); while ($dnn = $q->fetch()) { // 处理每条玩家数据 // 比如 echo $dnn['username'] . " - 积分:" . $dnn['points']; print_r($dnn); }
小提示:如果不需要去重(你的场景里两个查询的结果不会重复),可以用
UNION ALL替代UNION,执行速度会更快,因为它不需要做去重校验。
解决方案2:开启多语句支持并处理多结果集(仅特殊场景使用)
如果你因为某些原因必须分开执行两个查询,需要在初始化PDO时开启多语句支持,然后手动切换结果集:
// 初始化PDO时开启多语句属性,同时开启异常模式方便调试 $pdo = new PDO( 'mysql:host=你的数据库地址;dbname=你的数据库名;charset=utf8mb4', '你的用户名', '你的密码', [ PDO::MYSQL_ATTR_MULTI_STATEMENTS => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ] ); // 注意两个SQL之间要加分号分隔 $sql = "SELECT * FROM allplayers WHERE points > 0 ORDER BY points DESC; SELECT * FROM allplayers WHERE points = 0 AND qualified > 0;"; $q = $pdo->query($sql); // 处理第一个结果集(积分>0的玩家) echo "--- 积分大于0的玩家 ---\n"; while ($dnn = $q->fetch()) { print_r($dnn); } // 切换到第二个结果集 $q->nextRowset(); // 处理第二个结果集(积分=0但合格数>0的玩家) echo "\n--- 积分等于0但合格数大于0的玩家 ---\n"; while ($dnn = $q->fetch()) { print_r($dnn); }
重要提醒:开启多语句支持会提升SQL注入的风险,如果你的SQL里包含用户输入内容,一定要用PDO预处理语句,绝对不能直接把用户输入拼接进SQL字符串里!
内容的提问来源于stack exchange,提问作者JasperDaDolphin
相关产品推荐
相关产品推荐

