在使用CodeIgniter(特別是CodeIgniter 3)開發過程中,有時候我們需要執行包含多個SQL 查詢的語句塊(Multi-Query)。例如,我們可能希望一次性調用多個存儲過程,或在一個請求中執行多個查詢以提高效率。
但在使用多語句查詢時,一個常見問題是:只有第一個結果集可被訪問,其它結果集無法獲取。這是因為在使用MySQLi 驅動的情況下,CodeIgniter 並不會自動處理多個結果集。為了解決這個問題,我們就需要手動調用$this->db->next_result()方法來清理前一個結果集,並讓系統準備好處理下一個。
本文將向你展示如何在CodeIgniter 中正確使用next_result()來處理多語句查詢。
假設你有一個存儲過程文件,或者直接在控制器中執行類似如下的SQL:
$sql = "
CALL get_users();
CALL get_orders();
";
為了執行這類多語句SQL,你可以使用query()方法並手動管理結果集:
$result = $this->db->query("CALL get_users();");
if ($result) {
$users = $result->result();
// 清理第一個結果集
$result->free_result();
$this->db->next_result();
// 獲取第二個結果集
$result2 = $this->db->query("CALL get_orders();");
if ($result2) {
$orders = $result2->result();
// 再次清理
$result2->free_result();
$this->db->next_result();
}
}
這種方式適用於每次只調用一個存儲過程,然後再手動執行下一條語句。但若你希望一次性執行多個SQL 語句,比如用以下方式:
$sql = "
CALL get_users();
CALL get_orders();
CALL get_products();
";
則可以藉助MySQLi 原生的multi_query()功能實現。
在CodeIgniter 中,如果你使用的是MySQLi 驅動,你可以這樣操作:
$mysqli = $this->db->conn_id; // 獲取底層的 MySQLi 連接資源
$sql = "
CALL get_users();
CALL get_orders();
CALL get_products();
";
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
// 處理當前結果集
$data[] = $result->fetch_all(MYSQLI_ASSOC);
$result->free();
}
} while ($mysqli->more_results() && $mysqli->next_result());
}
這段代碼會依次獲取多個結果集,並使用next_result()準備好下一個。
雖然你可以直接用multi_query() ,但強烈建議將多語句分開執行,尤其是當你對安全性和穩定性有較高要求時。對於數據庫操作,推薦以下做法:
在每次查詢後調用free_result()和next_result()清理連接。
避免在模型中直接寫多個CALL ,而是封裝為單個調用,邏輯控制放在PHP 層。
如果必須使用multi_query() ,確保你處理了所有返回的結果集,避免“Commands out of sync”錯誤。
你可以把這個過程封裝成模型方法,返回包含多個數據集的數組:
public function get_multi_data()
{
$mysqli = $this->db->conn_id;
$sql = "
CALL get_users();
CALL get_orders();
CALL get_products();
";
$data = [];
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
$data[] = $result->fetch_all(MYSQLI_ASSOC);
$result->free();
}
} while ($mysqli->more_results() && $mysqli->next_result());
}
return $data;
}
控制器中你可以這樣調用:
$this->load->model('Data_model');
$result_sets = $this->Data_model->get_multi_data();
$users = $result_sets[0];
$orders = $result_sets[1];
$products = $result_sets[2];
調試多語句查詢時,建議開啟CodeIgniter 的日誌功能,並觀察application/logs中的內容,便於排查錯誤。