【问题标题】:PDOStatement::nextRowSet() is broken in MySQL 5.6.16 on WindowsPDOStatement::nextRowSet() 在 Windows 上的 MySQL 5.6.16 中被破坏
【发布时间】:2014-10-23 05:11:23
【问题描述】:

This question without an accepted answer 引发了 MySQL 的一个灾难性问题,我在 Windows 上的 MySQL 5.6.16 版本上以修改后的形式遇到了这个问题。

这个问题很容易重现:我将它包含在此处(从上面链接的问题中复制,但更改适用于我的代码):

$pdo = /* connection stuff here */
$sql = "call test();"; // call stored procedure - see below
$statement = $connection->query($sql);
do {
    $rowset = $statement->fetchAll(PDO::FETCH_ASSOC);
    if($rowset) {
        // Do stuff with $rowset
    }
} while($statement->nextRowset());

这里是存储过程test的定义:

DELIMITER $$
DROP PROCEDURE IF EXISTS `test`$$
CREATE PROCEDURE `test`()
BEGIN    
    SELECT 1; SELECT 2; SELECT 3; SELECT 4;
END$$
DELIMITER ;

我的代码和上面链接的代码之间的唯一区别是我将 SQL 查询打包到一个存储过程中。

在我的例子中,while 语句返回 true 四次,而不是三次(应该只是三次)。第四次之后,fetchAll(...) 会抛出 SQLSTATE[HY000]: General error 错误。

不幸的是,这个问题是灾难性的。除了使用nextRowSet() 函数之外,PDO 没有其他方法可以迭代到以下行集。因此,我可能会恢复到以前版本的 MySQL 以解决此问题。

我发现了两个似乎表明此问题的链接,在此处列出: https://bugs.php.net/bug.php?id=67130http://permalink.gmane.org/gmane.comp.php.devel/81518

如果确认这确实是 Windows 上 MySQL 5.6.16 版的错误,我将不胜感激。更重要的是,我希望有一个解决方法。谢谢。

【问题讨论】:

  • mysqli "can" (as I recall) 在结果集之间切换,但需要将整个应用程序移动到另一个数据库交互层。
  • 为什么不能将所有这些字符串作为 4 个单独的查询运行?
  • @silkfire 我已经更新了我的问题以添加重要的细节(很抱歉,当我第一次发布问题时没有这样做)。现在的代码与我运行的代码 100% 相同。事实上,SQL 是嵌入在存储过程中的。对于我的实际应用,查询要复杂得多,而且不容易重构。
  • @DanNissenbaum 实际上,我只是在我的 WAMP 安装中使用 MySQL 5.6.17 尝试了您的代码,只要我使用 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true); 启用模拟准备,它就可以出色地工作。

标签: php mysql windows pdo


【解决方案1】:

我对 PDO::nextRowset() 也有同样的问题,因为即使没有更多可用的行集它也会返回 true,因此在调用 fetchAll() 时,它会引发异常 HY000。 (在 PHP 5.5.12 windows、Mysql 5.5.17 linux 上测试)

解决此问题的方法是在获取行集之前使用方法 PDO::columnCount() 检查列数。如果它不为零,则您有一个有效的行集,因此您可以调用 PDO::fetchAll()。

即使 PDO::nextRowset() 报告为 true,columnCount() 也会在移动到下一个行集之前报告列数。

例子:

while ($objQuery->columnCount()) {
    $tab[] = $objQuery->fetchAll(\PDO::FETCH_ASSOC);
    $objQuery->nextRowset();
}

【讨论】:

    【解决方案2】:

    如果问题是由多个结果集引起的,那么最好的解决方法可能是找到避免在单个查询中出现多个结果集的方法。

    例如,如果预期结果的格式相同(我认为它们可能是因为您打算使用相同的代码来处理所有这些结果),那么您可能会使用 UNION 将四个查询组合在一起。

    SELECT 1
    UNION ALL
    SELECT 2
    UNION ALL
    SELECT 3
    UNION ALL
    SELECT 4;
    

    如果做不到这一点,您可以为每个 SELECT 执行单独的查询,并将结果交给函数进行处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-10
      • 2013-03-10
      • 1970-01-01
      • 2014-04-29
      • 1970-01-01
      • 2020-02-15
      • 2013-01-12
      • 1970-01-01
      相关资源
      最近更新 更多