【问题标题】:PDO::query() run into "Cannot execute queries while other unbuffered queries are active."PDO::query() 遇到“在其他无缓冲查询处于活动状态时无法执行查询”。
【发布时间】:2015-03-19 22:48:22
【问题描述】:

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

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

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

  1. 查询游标没有像这里提到的closeCursor() 关闭; Causes of MySQL error 2014 Cannot execute queries while other unbuffered queries are active
  2. 有两个以上的查询,其中一条语句如下所述:PDO Cannot execute queries while other unbuffered queries are active
  3. 这里提到的 mysql-driver 中的一个错误:What is causing PDO error Cannot execute queries while other unbuffered queries are active?

在我的情况下,以上所有内容都没有帮助,我花了一些时间才解决问题。这是我的代码(伪代码):

$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() 不起作用?调用时光标关闭。

【问题讨论】:

  • "当调用时,游标已关闭" SELECT * FROM database 的游标是,但是其他游标呢?

标签: php mysql pdo unbuffered-queries


【解决方案1】:

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

直接引用自PDO::querymanual page

如果您在下次调用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 对象返回。

【讨论】:

    【解决方案2】:

    我也遇到过这个问题。这很可能是一个错误。如果我们采用以下代码,那么您将看到它如何失败并显示消息“一般错误: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-&gt;query("USE test"); 更改为$pdo-&gt;exec("USE test");,它将起作用。如果您将$pdo-&gt;setAttribute(\PDO::ATTR_EMULATE_PREPARES, false); 更改为$pdo-&gt;setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);,它也可以工作。不过我还没有找到合适的解决方案。

    【讨论】:

      【解决方案3】:

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

      执行后: $stmt = db::getInstance()->prepare("呼叫电话(:phone)");

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

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

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

      就是这样。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2011-01-05
          • 2015-03-28
          • 2014-09-18
          • 2017-11-09
          • 1970-01-01
          • 1970-01-01
          • 2014-05-13
          相关资源
          最近更新 更多