在使用 PHP 的 MySQLi 扩展进行数据库多查询(multi-query)操作时,next_result() 是一个至关重要的函数。它用于处理存储过程或一次性发送多条 SQL 语句后的多个结果集。但很多开发者在使用 next_result() 时,会忽略一个细节:在调用 next_result() 之前,如果没有清空上一个结果集,可能会导致严重的问题。
使用 mysqli::multi_query() 执行多条 SQL 语句时,每一条语句都可能返回一个结果集。你需要用 store_result() 或 use_result() 来处理当前的结果集,然后再用 next_result() 移动到下一个结果集。
$mysqli = new mysqli("localhost", "user", "password", "database");
$sql = "SELECT * FROM users; SELECT * FROM products;";
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_assoc()) {
print_r($row);
}
$result->free(); // 非常重要的一步
}
} while ($mysqli->next_result());
}
mysqli::next_result() 的工作前提是当前结果集已被清空或释放。如果你跳过了 store_result() 或 free() 步骤,next_result() 可能无法正确移动到下一个结果集,导致后续查询结果永远不会被处理。
这是最常见的错误信息:
Commands out of sync; you can't run this command now
这个错误意味着你对 MySQL 的操作顺序不对,比如在处理完当前结果集前,就尝试执行新查询或访问下一结果集。
虽然 PHP 的垃圾回收机制通常能自动处理资源,但在大数据量或长连接场景下,如果不手动 free() 当前结果集,有可能造成内存缓慢增长,最终影响应用性能。
始终调用 store_result() 并及时 free() 当前结果集。
使用清晰的循环结构来确保每一个结果集都被处理干净。
为每个步骤添加错误检查,避免逻辑漏网之鱼。
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
// 处理结果
$result->free();
} else {
if ($mysqli->errno) {
echo "查询失败: " . $mysqli->error . "<br>";
}
}
} while ($mysqli->more_results() && $mysqli->next_result());
}
在使用 multi_query() 和 next_result() 时,务必牢记:处理完一个结果集再去请求下一个,是你与数据库良好互动的基本礼仪。不然,你可能很快会在 gitbox.net 的 bug 提交系统里,看到很多莫名其妙的 “Commands out of sync” 报错。