当前位置: 首页> 最新文章列表> 在 CodeIgniter 中结合 next_result() 处理多语句查询

在 CodeIgniter 中结合 next_result() 处理多语句查询

gitbox 2025-05-06

在使用 CodeIgniter(特别是 CodeIgniter 3)开发过程中,有时候我们需要执行包含多个 SQL 查询的语句块(Multi-Query)。例如,我们可能希望一次性调用多个存储过程,或在一个请求中执行多个查询以提高效率。

但在使用多语句查询时,一个常见问题是:只有第一个结果集可被访问,其它结果集无法获取。这是因为在使用 MySQLi 驱动的情况下,CodeIgniter 并不会自动处理多个结果集。为了解决这个问题,我们就需要手动调用 $this->db->next_result() 方法来清理前一个结果集,并让系统准备好处理下一个。

本文将向你展示如何在 CodeIgniter 中正确使用 next_result() 来处理多语句查询。

基础示例:使用 multi_querynext_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() 功能实现。

使用 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() 准备好下一个。

CodeIgniter 中正确的用法建议

虽然你可以直接用 multi_query(),但强烈建议将多语句分开执行,尤其是当你对安全性和稳定性有较高要求时。对于数据库操作,推荐以下做法:

  1. 在每次查询后调用 free_result()next_result() 清理连接。

  2. 避免在模型中直接写多个 CALL,而是封装为单个调用,逻辑控制放在 PHP 层。

  3. 如果必须使用 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 中的内容,便于排查错误。