8

也许其他人和我有同样的问题。我遇到了错误:

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

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

  1. closeCursor()查询游标没有像这里提到的那样关闭;MySQL 错误 2014 的原因在其他无缓冲查询处于活动状态时无法执行查询
  2. 一个语句有两个以上的查询,如下所述:PDO Cannot execute queries while other unbuffered queries are active
  3. 此处提到的 mysql-driver 中的错误:什么导致 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() 不起作用?调用时,游标关闭。

4

4 回答 4

4

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

直接从PDO::query 手册页引用:

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

你打电话closeCursor$stmt这是真的,但你还没有关闭你创建的所有游标:

//<-- 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::query现在来看和之间的主要区别PDO::exec。再次引用手册:

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

然而:

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

于 2015-01-21T12:19:21.757 回答
3

我也遇到过这个问题。这很可能是一个错误。如果我们采用以下代码,那么您将看到它如何失败并显示消息“一般错误: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);也将工作。不过,我还没有找到合适的解决方案。

于 2018-04-13T12:27:22.897 回答
0

请注意,如果您尝试获取非 SELECT 查询(例如 - UPDATE/INSERT/ALTER/CREATE),也会发生这种情况

于 2020-12-20T09:35:07.813 回答
0

我通过以下步骤解决问题:

执行后: $stmt = db::getInstance()->prepare("CALL phone(:phone)");

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

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

我的解决方法是:一条语句调用“CALL 电话(:电话)”过程,另一条语句使用“SELECT * FROM 数据库”执行查询。

这就对了。

于 2020-08-09T14:32:56.373 回答