PDO::query() 遇到“当其他未缓冲的查询处于活动状态时无法执行查询”


PDO::query() run into "Cannot execute queries while other unbuffered queries are active."

Maybee 其他人也有和我一样的问题。我运行错误:

当其他未缓冲查询处于活动状态时,无法执行查询。考虑使用 PDOStatement::fetchAll()。或者,如果您的代码只会针对MySQL运行,您可以启用查询通过设置 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY 属性进行缓冲。

在PDO上。与提到的许多线程一样,错误可能至少是以下问题之一:

  1. 查询游标未在此处使用closeCursor()关闭;MySQL 错误 2014 的原因 在其他未缓冲查询处于活动状态时无法执行查询
  2. 有两个以上的查询具有一个语句,如下所示: PDO 在其他未缓冲查询处于活动状态时无法执行查询
  3. mysql 驱动程序中的一个错误,如下所述:是什么导致了 PDO 错误 在其他未缓冲查询处于活动状态时无法执行查询?

就我而言,上述所有内容都没有帮助,我花了一段时间才解决问题。 这是我的代码(伪代码):

$stmt->startTransaction();
$stmt = db::getInstance()->prepare("CALL phones(:phone)");
$stmt->prepare('SELECT * FROM database');
$stmt->execute();
$aData = $stmt->fetchAll();
$stmt->closeCursor();
$stmt->query("USE sometable;");

在我将其更改为:

$stmt->startTransaction();
$stmt = db::getInstance()->prepare("CALL phones(:phone)");
$stmt->prepare('SELECT * FROM database');
$stmt->execute();
$aData = $stmt->fetchAll();
$stmt->closeCursor();
$stmt->exec("USE sometable;");

它对我有用。查询和执行有什么区别?

PDO::exec() - "Execute an SQL statement and return the number of affected rows"
PDO::query() - "Executes an SQL statement, returning a result set as a PDOStatement object"

为什么在这种情况下 PDO::query() 不起作用?调用时,游标处于关闭状态。

虽然可以想象您在这里遇到了 mysql 驱动程序错误,但我们无法确定这一点,因为您没有向我们提供该信息(您使用的是什么版本的 PHP?它是否使用 mysqlnd => 与php -i | grep mysqlnd进行检查?代码的其余部分是什么样的?
对于您的问题,还有许多其他可能的解释。我怀疑问题实际上是您未能关闭所有光标和/或获取所有结果,因为$stmt大量重复使用:

直接引自PDO::query手册页:

如果在发出对 PDO::query() 的下一次调用之前未获取结果集中的所有数据,则调用可能会失败。调用 PDOStatement::closeCursor() 以释放与PDOStatement对象关联的数据库资源,然后再发出对 PDO::query() 的下一次调用。

您在 $stmt 上调用 closeCursor ,这是真的,但您尚未关闭您创建的所有游标:

//<-- what is $stmt here?
$stmt->startTransaction();
//no matter, you've reassigned it a PDOStatement instance
$stmt = db::getInstance()->prepare("CALL phones(:phone)");
//Huh? You're preparing yet another query on an instance of PDOStatement?
$stmt->prepare('SELECT * FROM database');
//you're executing this one, though
$stmt->execute();
//and fetching all data
$aData = $stmt->fetchAll();
//and closing this last statement
$stmt->closeCursor();

但是,分配给$stmt的第一个语句(存储过程调用)呢?该光标未在任何地方关闭

现在是PDO::queryPDO::exec之间的主要区别。再次引用手册:

PDO::exec() 不返回 SELECT 语句的结果。

而:

PDO::query()在单个函数调用中执行 SQL 语句,并将该语句返回的结果集(如果有)作为 PDOStatement 对象返回。

我也遇到了这个问题。这很可能是一个错误。如果我们采用以下代码,那么您将看到它是如何失败的,并显示消息"一般错误:2014 在其他未缓冲查询处于活动状态时无法执行查询。考虑使用 PDOStatement::fetchAll()."

$pdo = new 'PDO("mysql:host=localhost", "root", "");
$pdo->setAttribute('PDO::ATTR_ERRMODE, 'PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute('PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query("USE test");

如果将$pdo->query("USE test");更改为$pdo->exec("USE test");它将起作用。如果将$pdo->setAttribute('PDO::ATTR_EMULATE_PREPARES, false);更改为$pdo->setAttribute('PDO::ATTR_EMULATE_PREPARES, true);它也可以工作。不过,我还没有找到合适的解决方案。

我用步骤解决了这个问题:

从执行之后:$stmt = db::getInstance()->prepare("CALL phones(:p hone)");

我关闭:$stmt->startTransaction();

之后,我再次打开交易以使用以下查询:$stmt->prepare('SELECT * FROM database');

我的解决方法是:一个语句调用过程"CALL phone(:p hone)",另一个语句使用"SELECT * FROM 数据库"执行查询。

就是这样。

请注意,如果您尝试获取非 SELECT 查询(例如 - 更新/插入/更改/创建),也会发生这种情况