【问题标题】:Zend db with prepared statement doesn't fetch all data带有准备好的语句的 Zend db 不会获取所有数据
【发布时间】:2013-10-23 23:11:42
【问题描述】:

先有罪代码:

$preparedGetData = $db->prepare("CALL getData(?)");
foreach($userSet as $r) {
    $preparedGetData->execute(array($r['id_user']));
    $rs = $preparedGetData->fetchAll();
    $preparedGetData->closeCursor();
}

说明

getData = mysql 中的存储过程
$db = Zend_Db_Adapter_Pdo_Mysql 实例(使用 Zend 版本 1.10.0)

症状

  • 当我在第二个周期中省略 closeCursor 时,我已经收到错误:

    PHP 致命错误:未捕获异常 'PDOException' 并带有消息 'SQLSTATE[HY000]:一般错误:2014 在其他无缓冲查询处于活动状态时无法执行查询。考虑使用 PDOStatement::fetchAll()。或者,如果您的代码只针对 mysql 运行,您可以通过设置 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY 属性来启用查询缓冲。

  • 但我正在使用fetchAll !!!

  • 当我添加 closeCursor 时,结果不完整。在查询浏览器中调用 CALL getData('3872') 会返回 1 行 72 列。上面的代码所做的相同返回只有前 41 列的 1 行。

我做错了什么?

Edit2:半解决方案

代码更新为:

$preparedGetData = $db->prepare("CALL getData(?)");
foreach($userSet as $r) {
    $preparedGetData->execute(array($r['id_user']));

    $rs=array();

    do {
        try {
            $partial_rowset = $preparedGetData->fetchAll(); // When I put fetchAll() after the end of the cycle, I get empty resultset.
        } catch (PDOException $error) { // The PDOException doesn't get caught here. Why?
            error_log($error);
        } catch (Exception $error) { 
            error_log($error);
        }
        if ($partial_rowset) {
            $rs=array_merge($rs,$partial_rowset);
        }
    } while ($preparedGetData->nextRowset());
}

症状

  • 出现错误:
    PHP 致命错误:未捕获的异常 'PDOException' 带有消息 'SQLSTATE[HY000]:一般错误
    下一个异常 'Zend_Db_Statement_Exception' 和消息 'SQLSTATE[HY000]: General error' in /home/GIT/includes/Zend/Db/Statement/Pdo.php:294
    fetchAll在线。
  • 我可以使用通用异常捕获此错误。
  • 使用此代码,我得到所有 72 列。
  • 我认为这很糟糕,因为我故意捕获一般异常并将其转换为日志。我猜这也会成为性能问题(循环运行大约 10 000 次)。

【问题讨论】:

  • 我似乎记得一个关于存储过程和尾随状态的错误...如果您在->fetchAll() 之后调用$preparedGetData->nextRowset() 是否有机会?如果你暂时用纯PDO测试这个会发生什么,问题仍然存在还是在Zend代码中?

标签: php mysql prepared-statement zend-db


【解决方案1】:

MySQL 存储过程可能有多个结果集。也就是说,您可以在一个存储过程中运行多个 SELECT 查询,然后遍历这多个结果集。

这使得获取变得复杂,因为整个结果实际上就像一个数组数组的数组(多个结果集,每个结果集可能有多行,每行可能有多个列)。

fetchAll() 仅从 一个 结果集中获取所有行。所以当你调用一个存储过程时,你需要强制它刷新所有的结果集。也就是说,一直调用 nextRowset() 直到该函数返回 null。

Zend_Db API 以 PDO 为模型,因此您可以在 PDOStatement::nextRowset() 的文档中查看 nextRowset() 的示例用法。

不幸的是,没有像fetchAllRowsets()这样的功能。你可以自己做一个 while 循环。

【讨论】:

  • 是的,nextRowset() 多次返回true。但是按照第二遍文档中的 do-while 示例,我得到 PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error' in ...使用 fetch_all。知道为什么吗?
  • 仅供参考:possibly related bug(应该修复,但最近重新打开)
  • @Wrikken :是的,可能就是这样。如果他们修复它,我会等待,然后尝试删除受保护的块。到目前为止,不幸的是我不能使用 php 5.5,因为php5-json breaks firephp
  • @sumid:如果你使用mysql作为驱动,可以切换到mysqlnd吗?似乎问题较少。
  • @Wrikken :我都试过了。在这个问题上没有区别:-(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-05
  • 1970-01-01
相关资源
最近更新 更多