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

时间:2015-01-21 12:06:12

标签: php mysql pdo unbuffered-queries

也许其他一些人比我有同样的问题。 我跑过错误:

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上的

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

  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?
  4. 在我的情况下,以上所有都没有帮助,我花了一些时间才解决了问题。这是我的代码(伪代码):

    $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;");
    

    它适用于我的。 query和exec有什么区别?

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

4 个答案:

答案 0 :(得分:3)

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

直接引自PDO::query manual page

  

如果在下次调用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::queryPDO::exec之间存在重大差异。再次引用手册:

  

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

鉴于:

  

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

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

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

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

我的解决方法是:一个语句调用过程“ CALL phone(:phone)”,另一条语句执行“ SELECT * FROM database”查询。

就是这样。

答案 3 :(得分:0)

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