在實際開發過程中,尤其是在使用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 "1。 " . ($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 ! ??