You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP foreach循环执行存储过程出现2014错误的求助

解决PDO循环调用MySQL存储过程时的2014错误

在foreach循环中调用MySQL存储过程时,仅第一次执行成功,后续循环抛出以下错误:

SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.

已尝试设置PDO::MYSQL_ATTR_USE_BUFFERED_QUERY = true、调用closeCursor()但问题依旧,以下是解决方案及修改后的代码:


原配置文件(config.php)

<?php
// 数据库连接参数
$host = 'xxxxxx';
$db   = 'xxxxxx';
$user = 'root';
$pass = 'xxxxxx';
$port = "xxxxxx";
$charset = 'utf8mb4';

// 连接选项
$options = [
    \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
    \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
    \PDO::ATTR_EMULATE_PREPARES   => false,
    \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
];

$dsn = "mysql:host=$host;dbname=$db;charset=$charset;port=$port";
try {
     $pdo = new \PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
     throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

修改后的业务代码(actions.php)

require_once 'config.php';
$sprawujacyP = [
    [
        'plec' => 'Kobieta',
        'data_urodzenia' => '1998-01-14'
    ],
    [
        'plec' => 'Mężczyzna',
        'data_urodzenia' => '1998-01-14'
    ],
];
$id_r = 1;
$id_op = 3;
$outmsg = "123";
$sql = "CALL example_procedure(:id_r,:plec,:data_urodzenia,:id_op,:outmsg)";

foreach ($sprawujacyP as $sprawujacy) {
    try {
        // 每次循环重新准备语句,避免结果集残留
        $statement = $pdo->prepare($sql);
        // 使用bindValue绑定具体值,避免引用变量的循环问题
        $statement->bindValue(':id_r', $id_r, PDO::PARAM_INT);
        $statement->bindValue(':plec', $sprawujacy['plec'], PDO::PARAM_STR);
        $statement->bindValue(':data_urodzenia', $sprawujacy['data_urodzenia'], PDO::PARAM_STR);
        $statement->bindValue(':id_op', $id_op, PDO::PARAM_STR);
        // 输出参数仍用bindParam
        $statement->bindParam(':outmsg', $outmsg, PDO::PARAM_STR);
        
        $statement->execute();
        
        // 强制消耗所有结果集(存储过程可能返回多个结果集)
        do {
            $statement->fetchAll();
        } while ($statement->nextRowset());
        
        $statement->closeCursor();
    } catch(PDOException $e) {
        echo $e->getMessage();
    }   
}

关键修改点说明

  1. 每次循环重新准备语句:复用同一个PDOStatement时,可能残留未处理的结果集,重新初始化可彻底避免该问题
  2. 替换bindParam为bindValue:bindParam绑定的是变量引用,循环中变量值更新会导致绑定值不符合预期;bindValue直接传入当前循环的具体值,更稳定
  3. 遍历并消耗所有结果集:存储过程可能返回多个结果集(即使没有显式SELECT),通过nextRowset()+fetchAll()确保所有查询结果都被处理,避免未缓冲查询残留

内容的提问来源于stack exchange,提问作者SEO fKings

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 05:31:20