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(); } }
关键修改点说明
- 每次循环重新准备语句:复用同一个
PDOStatement时,可能残留未处理的结果集,重新初始化可彻底避免该问题 - 替换bindParam为bindValue:bindParam绑定的是变量引用,循环中变量值更新会导致绑定值不符合预期;bindValue直接传入当前循环的具体值,更稳定
- 遍历并消耗所有结果集:存储过程可能返回多个结果集(即使没有显式SELECT),通过
nextRowset()+fetchAll()确保所有查询结果都被处理,避免未缓冲查询残留
内容的提问来源于stack exchange,提问作者SEO fKings
相关产品推荐
相关产品推荐

