MySQLi multi_query() 允許單次呼叫執行多條以分號分隔的 SQL 語句,大幅減少網路往返延遲。本文示範批次 INSERT 實作,並說明混合執行 DML、結果集處理差異與錯誤捕獲機制。
<?php
// 1. 建立連線
$mysqli = new MySQLi("localhost", "root", "123456", "liuyan");
if ($mysqli->connect_error) die($mysqli->connect_error);
$mysqli->query("SET NAMES 'GBK'");
// 2. 組裝多條 SQL(以分號分隔)
$sqls = "INSERT INTO news(title, contents, datetime, hit) VALUES
('去哪兒網架構調整鋪墊上市','據接近去哪兒網的消息人士透露...','" . date('Y-m-d H:i:s') . "',30);";
$sqls .= "INSERT INTO news(title, contents, datetime, hit) VALUES
('告訴金主 視頻網站誰是NO.1','搜狐說,自己穩穩超過土豆...','" . date('Y-m-d H:i:s') . "',30);";
$sqls .= "INSERT INTO news(title, contents, datetime, hit) VALUES
('蘋果正滋生傲慢情緒','據國外媒體報道,沒有經歷重大挫折...','" . date('Y-m-d H:i:s') . "',30);";
// 3. 批次執行
$res = $mysqli->multi_query($sqls);
// 4. 結果判斷
if (!$res) {
echo "批次執行失敗:" . $mysqli->error;
} else {
echo "批次執行成功!";
}
// 5. 關閉連線
$mysqli->close();
?>
true:第一條 SQL 執行成功(不代表後續都成功)false:第一條 SQL 執行失敗關鍵:必須配合 more_results() / next_result() 遍歷所有結果才能確知完整執行狀態。
可在同一 multi_query 中混合 INSERT/UPDATE/DELETE:
$mixedSql = "
INSERT INTO log(event) VALUES('start');
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
DELETE FROM temp_cache WHERE expired < NOW();
INSERT INTO log(event) VALUES('end');
";
$mysqli->multi_query($mixedSql);
if ($mysqli->multi_query($sqls)) {
do {
// 處理每個結果集(SELECT 會有結果集,DML 則無)
if ($result = $mysqli->store_result()) {
// 有結果集(如 SELECT、SHOW、EXPLAIN)
while ($row = $result->fetch_assoc()) {
// 處理資料...
}
$result->free();
} else {
// 無結果集(INSERT/UPDATE/DELETE)
// 可透過 $mysqli->affected_rows 取得影響列數
echo "影響列數:" . $mysqli->affected_rows . "\n";
}
// 檢查是否還有下一個結果集
if ($mysqli->more_results()) {
echo "--- 處理下一個結果集 ---\n";
}
} while ($mysqli->next_result());
}
multi_query 建議不超過 1000 條或 1MB SQL 字串,避免超過 max_allowed_packetautocommit(false) / commit() / rollback() 中prepare() + 迴圈 execute(),更安全且支援參數綁定LOAD DATA,效能優於 multi_query 數量級next_result() 導致後續查詢報錯 "Commands out of sync"善用 multi_query 可顯著降低高延遲網路環境下的批次寫入耗時,但務必建立完整的結果遍歷與錯誤處理機制。