在实际开发过程中,尤其是在使用 MySQL 多查询(multi-query)功能时,经常会遇到需要处理多个结果集的情况。如果没有统一的处理方式,每次都手动调用 next_result() 和 store_result(),不仅麻烦,还容易出错。
为了让代码更加优雅、健壮,我们可以封装一个通用函数,自动处理所有的结果集。下面我将一步步带你了解怎么做。
在使用 mysqli 进行多查询时(即一次性发送多条 SQL 语句),每条语句对应一个结果集。使用 next_result() 可以让 mysqli 对象移动到下一个结果集,而 store_result() 则负责提取当前结果集的数据。
如果不正确地处理这些结果集,很容易导致连接异常,或下一次查询失败。因此,完整地清理所有结果集非常重要。
下面是一个示例,演示如何封装一个处理所有结果集的函数,并且返回所有数据的数组:
<?php
/**
* 执行多查询并处理所有结果集
*
* @param mysqli $mysqli MySQLi连接对象
* @param string $multiQuery 要执行的多条SQL查询语句(用分号隔开)
* @return array 返回一个包含所有结果集数据的数组
*/
function executeMultiQuery(mysqli $mysqli, string $multiQuery): array
{
$allResults = [];
if ($mysqli->multi_query($multiQuery)) {
do {
if ($result = $mysqli->store_result()) {
$data = [];
while ($row = $result->fetch_assoc()) {
$data[] = $row;
}
$allResults[] = $data;
$result->free();
} else {
// 当前结果可能是无结果集的,比如UPDATE或INSERT
if ($mysqli->errno) {
throw new Exception("MySQL错误:" . $mysqli->error);
}
$allResults[] = null;
}
} while ($mysqli->more_results() && $mysqli->next_result());
} else {
throw new Exception("执行多查询失败:" . $mysqli->error);
}
return $allResults;
}
// 示例用法
$mysqli = new mysqli('localhost', 'root', 'password', 'testdb');
if ($mysqli->connect_errno) {
die("连接失败:" . $mysqli->connect_error);
}
try {
$sql = "
SELECT * FROM users;
SELECT * FROM orders;
UPDATE products SET stock = stock - 1 WHERE id = 5;
";
$results = executeMultiQuery($mysqli, $sql);
// 输出所有查询结果
foreach ($results as $index => $resultSet) {
echo "第 " . ($index + 1) . " 个结果集:<br>";
if (is_array($resultSet)) {
foreach ($resultSet as $row) {
echo htmlspecialchars(json_encode($row)) . "<br>";
}
} else {
echo "(无返回结果,例如UPDATE或INSERT语句)<br>";
}
echo "<hr>";
}
} catch (Exception $e) {
echo "发生错误:" . $e->getMessage();
}
$mysqli->close();
?>
及时释放结果集资源:调用 $result->free() 非常重要,避免内存泄漏。
错误检测:如果 multi_query() 或某一轮 store_result() 出错,应及时捕获异常,避免后续操作继续出错。
适配无结果集的操作:UPDATE、INSERT、DELETE 等语句没有返回结果集,处理时需要做特殊判断。
通过封装处理多结果集,我们不仅让代码更加简洁,还能有效避免 MySQL 连接混乱的问题。如果你的项目中需要频繁处理多条 SQL 查询,强烈建议使用类似的方法进行标准化封装。
如果你想了解更多关于多查询的进阶使用,比如事务(transaction)结合多查询,或者如何在大项目中集成这样的封装,可以继续关注我们的网站:https://gitbox.net!??