首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP mysqli 批量執行 SQL 語句:multi_query 多查詢與多結果集完整處理指南

     編輯:PHP 相關知識

核心方法:mysqli::multi_query()

支持一次調用執行多條 SQL(以分號分隔),適用於批量 DML、DDL、混合語句。注意:返回結果集時需循環處理所有結果集,否則會導致「Commands out of sync」錯誤。

場景一:批量執行 INSERT/UPDATE/DELETE(無結果集)

<?php
$mysqli = new mysqli("localhost", "root", "root", "test");
if ($mysqli->connect_errno) die("連接失敗: " . $mysqli->connect_error);

$sql = "INSERT INTO user1 (name, password, email, age) VALUES ('AAA', MD5('AAA'), 'AAA@hu.com', 25);";
$sql .= "INSERT INTO user1 (name, password, email, age) VALUES ('BBB', MD5('BBB'), 'BBB@hu.com', 25);";
$sql .= "INSERT INTO user1 (name, password, email, age) VALUES ('CCC', MD5('CCC'), 'CCC@hu.com', 25);";
// 可混合:$sql .= "UPDATE user1 SET age=15 WHERE id=1; DELETE FROM user1 WHERE id=10;";

if ($mysqli->multi_query($sql)) {
    echo "批量執行成功,影響行數: " . $mysqli->affected_rows;
} else {
    echo "執行失敗: " . $mysqli->error;
}

$mysqli->close();

場景二:批量查詢(多結果集處理)

<?php
$mysqli = new mysqli("localhost", "root", "root", "test");
if ($mysqli->connect_errno) die("連接失敗: " . $mysqli->connect_error);

$sql = "SELECT * FROM user1;";
$sql .= "DESC user1;"; // 第二條查詢

if ($mysqli->multi_query($sql)) {
    do {
        // 獲取當前結果集
        if ($result = $mysqli->store_result()) {
            echo "=== 結果集 ===" . "<br>";
            while ($row = $result->fetch_row()) {
                foreach ($row as $val) echo "--$val";
                echo "<br>";
            }
            $result->free(); // 必須釋放,否則內存洩漏
        } else {
            // 無結果集的語句(INSERT/UPDATE),affected_rows 可用
            echo "無結果集語句,影響行數: " . $mysqli->affected_rows . "<br>";
        }

        // 檢查是否還有下一個結果集
        if ($mysqli->more_results()) {
            echo "******** 新結果集 ********<br>";
        } else {
            break;
        }
    } while ($mysqli->next_result()); // 移動到下一個結果集
} else {
    echo "執行失敗: " . $mysqli->error;
}

$mysqli->close();

關鍵流程圖解

multi_query(sql)
    │
    ├─► store_result() ──► fetch_row() 循環 ──► free()
    │
    ├─► more_results() ? ── 是 ──► next_result() ──► 循環
    │
    └─► 否 ──► 結束

常見錯誤與解決

錯誤原因解決
Commands out of sync未處理完所有結果集就執行下一條查詢務必循環 next_result() 直到 more_results() 為 false
內存耗盡大結果集未及時 free()每個結果集用完立即 $result->free()
SQL 語法錯誤導致後續不執行multi_query 遇錯誤停止單獨測試每條 SQL;或拆分為多次 multi_query
預處理語句不能用 multi_queryprepare() 單條執行批量寫入用事務 + prepare 循環 execute

性能對比:multi_query vs 事務 + prepare

// 方案 A:multi_query(網絡往返 1 次,但無法參數化,防注入弱)
$mysqli->multi_query($hugeSql);

// 方案 B:事務 + prepare(推薦,安全、可複用執行計劃)
$mysqli->begin_transaction();
$stmt = $mysqli->prepare("INSERT INTO t (a,b) VALUES (?,?)");
foreach ($data as $row) {
    $stmt->bind_param('ss', $row['a'], $row['b']);
    $stmt->execute();
}
$mysqli->commit();

結論:批量寫入優先用 事務 + 預處理;multi_query 適合導入 SQL 文件、執行 DDL 腳本、混合無參數語句。

PDO 不支持 multi_query

PDO 無對應方法,需自行分割 SQL 字符串循環 exec(),或使用事務 + 預處理。

安全提示

  • 絕不將用戶輸入直接拼接進 multi_query,極高風險 SQL 注入。
  • 僅用於可信 SQL 文件導入、內部批量腳本執行。
  • 生產環境寫入操作嚴格使用預處理 + 事務。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved