带有预准备语句的Zend db不会获取所有数据

时间:2013-10-23 23:11:43

标签: php mysql prepared-statement zend-db

首先是有罪的代码:

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

  • 但我正在使用fetchAll !!!

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

我做错了什么?

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致命错误:带有消息'SQLSTATE [HY000]的未捕获异常'PDOException':常规错误
    下一个异常'Zend_Db_Statement_Exception',并在/home/GIT/includes/Zend/Db/Statement/Pdo.php:294中显示消息'SQLSTATE [HY000]:常规错误' 与fetchAll
  • 一致
  • 我可以使用通用异常捕获此错误。
  • 使用此代码,我获得了所有72列。
  • 我觉得这很讨厌,因为我故意捕捉到一般异常而只是把它变成了日志。我想这也会成为一个性能问题(周期大约是10000次)。

1 个答案:

答案 0 :(得分:2)

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

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

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

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

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