mysqli::multi_query() 允許單次調用發送多條 SQL 語句(以分號分隔),配合 store_result()、next_result()、more_results() 遍歷所有結果集,適用於批量報表、Schema 遷移、減少網絡往返場景。
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->set_charset('utf8mb4');
$sql = "SELECT * FROM news LIMIT 4; SELECT * FROM users; SELECT COUNT(*) AS c FROM logs;";
if ($mysqli->multi_query($sql)) {
do {
// 獲取當前結果集(SELECT/SHOW/EXPLAIN 等產生結果集的語句)
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_assoc()) {
// 處理行數據
print_r($row);
}
$result->free(); // 釋放內存
}
// 判斷是否還有後續結果集
if ($mysqli->more_results()) {
echo "--- Next Result Set ---\n";
}
} while ($mysqli->next_result()); // 移動到下一結果集,無則返回 false
}
$mysqli->close();
multi_query() 返回 bool,僅表示首條語句發送成功,**不代表所有語句執行成功**。store_result() 返回 mysqli_result 或 false(非結果集語句如 INSERT/UPDATE、或錯誤)。next_result() 同時執行「釋放前一結果集」與「準備下一結果集」,返回 bool 指示是否存在下一結果集。more_results() 僅檢查是否還有結果集,**不移動指針**。$mysqli->errno,若非 0 則發生錯誤,後續結果集不可用。$mysqli->autocommit(false);
$sql = "UPDATE accounts SET balance=balance-100 WHERE id=1;
UPDATE accounts SET balance=balance+100 WHERE id=2;
SELECT balance FROM accounts WHERE id IN (1,2);";
if ($mysqli->multi_query($sql)) {
$hasError = false;
do {
if ($mysqli->errno) { $hasError = true; break; }
if ($result = $mysqli->store_result()) {
// 只有最後一條 SELECT 會進入這裡
$row = $result->fetch_assoc();
echo "Final balances: " . json_encode($row) . "\n";
$result->free();
}
} while ($mysqli->next_result());
if ($hasError) {
$mysqli->rollback();
echo "Transaction rolled back: " . $mysqli->error;
} else {
$mysqli->commit();
echo "Transaction committed.";
}
}
store_result(),改用 use_result() 非緩衝模式(但不可 next_result() 前讀完)。PDO 設計上**不支援多語句**(安全考量,防注入)。若用 PDO,請改用事務 + 循環執行單條預處理語句,或封裝 mysqli 專用類僅處理批量場景。
掌握 multi_query 完整流程,能在 Schema 部署、數據初始化、批量報表等場景大幅提升執行效率。