使用PDO进行行计数

Jam*_*mes 184 php mysql pdo

围绕着许多相互矛盾的陈述.在PHP中使用PDO进行行计数的最佳方法是什么?在使用PDO之前,我只是简单地使用了mysql_num_rows.

fetchAll 是我不想要的东西,因为我有时可能会处理大型数据集,所以对我的使用不利.

你有什么建议吗?

kar*_*m79 252

$sql = "SELECT count(*) FROM `table` WHERE foo = bar"; 
$result = $con->prepare($sql); 
$result->execute(); 
$number_of_rows = $result->fetchColumn(); 
Run Code Online (Sandbox Code Playgroud)

不是最优雅的方式,加上它涉及额外的查询.

PDO有PDOStatement::rowCount(),这显然也没有在MySQL的工作.太痛苦了.

来自PDO Doc:

对于大多数数据库,PDOStatement :: rowCount()不返回受SELECT语句影响的行数.相反,使用PDO :: query()发出带有与预期SELECT语句相同的谓词的SELECT COUNT(*)语句,然后使用PDOStatement :: fetchColumn()来检索将返回的行数.然后,您的应用程序可以执行正确的操作

编辑:上面的代码示例使用一个预准备语句,在许多情况下,可能不需要计算行,所以:

$nRows = $pdo->query('select count(*) from blah')->fetchColumn(); 
echo $nRows;
Run Code Online (Sandbox Code Playgroud)

  • 使用这种方法,`fetchColumn()`返回一个字符串"1234"...你的EDIT有`echo count($ nRows);` - `count()`是一个数组函数:P.我还建议将`fetchColumn()`的结果类型转换为整数.`$ count =(int)$ stmt-> fetchColumn()` (10认同)
  • 这意味着需要进行额外的数据库查询。我假设他已经完成了选择查询,现在想知道返回了多少行。 (2认同)

Cha*_*rch 84

正如我之前在回答类似问题时写的那样,唯一有效的原因mysql_num_rows()是因为它在内部提取所有行来为您提供信息,即使它看起来不像你.

所以在PDO中,您的选择是:

  1. 使用MySQL的FOUND_ROWS()功能.
  2. 使用PDO的fetchAll()函数将所有行提取到数组中,然后使用count()它.
  3. SELECT COUNT(*)像karim79建议的那样,做一个额外的查询.

  • 感谢您对mysql_num_rows()的进一步教育,看起来这可能是我给自己的一个重要瓶颈.再次感谢. (8认同)
  • fetch_all实际上是fetchAll():) (2认同)
  • 如果结果很大,则不建议选择选项 2。 (2认同)

You*_*nse 24

在使用PDO之前我只是简单地使用了mysql_num_rows().

不应该首先使用它.

mysql_num_rows(),以及PDOStatement::rowCount()暗示您已经选择了您的数据.在这种情况下,这种功能只有两种可能的用例:

  1. 您只是为了获得计数而选择数据.
  2. 您想知道您的查询是否返回任何行.

前者永远不应该被使用.永远不应该选择行来计算它们,因为您的服务器确实可能因为返回大数据集而窒息.

此外,仅选择行来计算它们是没有意义的.一个count(*)查询必须改为运行,与只返回一行.

第二个用例不是灾难性的,而是毫无意义的:如果你需要知道你的查询是否返回了任何数据,你总是拥有数据本身!

比如,如果您只选择一行,则只需获取它,然后检查结果:

$stmt->execute();
$row = $stmt->fetch();
if ($row) { // here! as simple as that
}
Run Code Online (Sandbox Code Playgroud)

如果你需要获得很多行,那么你可以使用fetchAll().

fetchAll() 是我不想要的东西,因为我有时可能会处理大型数据集

请注意,在Web应用程序中,您不应该选择大量的行.只应选择将在网页上实际使用的行.为此,LIMIT必须使用SQL中的一个或类似的子句.对于如此适量的数据,可以使用fetchAll()

在极少数情况下,当您需要选择真正的大量行(例如在控制台应用程序中)时,为了减少使用的内存量,您必须使用无缓冲的查询,但在这种情况下rowCount()将无法使用无论如何,这个功能也没用.

所以你看,没有用例也rowCount()没有用于替换它的额外查询,如接受的答案中所建议的那样.

  • @andufo不是.请记住:开发人员应该**从不**这样做.搜索查询永远不会返回所有284行.15必须返回显示和**一行**来自单独的查询,以告诉284被发现. (4认同)
  • 这是一个非常好的观点 - 起初不直观,但有效.大多数人忘记了两个简单的SQL查询比一个稍微大一点的查询速度快*.为了证明任何计数,你必须有一个非常慢的查询,无法进行优化,并且可能产生很少的结果.感谢您指出了这一点! (2认同)
  • @matteo你没有任何理由这样做。这些行已经被提取到一个方便的数组中,您只需 foreach() 它 (2认同)

Dan*_*Dan 19

这是超级晚了,但我遇到了问题,我这样做:

function countAll($table){
   $dbh = dbConnect();
   $sql = "select * from `$table`";

   $stmt = $dbh->prepare($sql);
    try { $stmt->execute();}
    catch(PDOException $e){echo $e->getMessage();}

return $stmt->rowCount();
Run Code Online (Sandbox Code Playgroud)

它非常简单,容易.:)

  • 选择所有数据只是为了对它进行计数,这违反了数据库交互的最基本规则. (17认同)
  • 它不适用于无缓冲的查询. (3认同)

Eri*_*nke 18

我最终使用了这个:

$result = $db->query($query)->fetchAll();

if (count($result) > 0) {
    foreach ($result as $row) {
        echo $row['blah'] . '<br />';
    }
} else {
    echo "<p>Nothing matched your query.</p>";
}
Run Code Online (Sandbox Code Playgroud)


Ten*_*ter 11

这篇文章很老但是用PDO获取行计数很简单

$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
Run Code Online (Sandbox Code Playgroud)

  • 选择所有数据只是为了统计它,违反了数据库交互的最基本规则。 (4认同)
  • 请参阅karim79的答案中引用的文档.这有时可行,但不可靠. (3认同)

小智 5

这是一个老帖子,但在寻找替代方案时感到沮丧.非常不幸的是,PDO缺乏此功能,特别是因为PHP和MySQL倾向于齐头并进.

使用fetchColumn()存在一个令人遗憾的缺陷,因为fetchColumn()会将指针移动到下一行,因此无法再使用该结果集(有效).例如,如果您有类似的结果

  1. 水果 - >香蕉
  2. 水果 - >苹果
  3. 水果 - >橙色

如果使用fetchColumn(),你会发现返回了3个水果,但如果你现在循环结果,你只有两列,fetchColumn()的价格是第一列结果的丢失输出了多少行.这导致了草率编码,并且如果实施则完全错误的结果.

所以现在,使用fetchColumn()你必须实现全新的调用和MySQL查询才能得到一个新的工作结果集.(我希望,自上次查询以来没有改变),但不太可能,但它可能会发生.此外,所有行计数验证的双查询开销.对于这个例子来说这个很小,但是在一个连接的查询中解析了200万行,而不是一个令人愉快的代价.

我喜欢PHP并且每天都使用PHP来支持参与其开发以及整个社区的每个人,但是真的希望在将来的版本中解决这个问题.对于PHP PDO来说,这是'我'唯一的抱怨,否则这是一个很棒的课程.


小智 5

如果您只想获取行数(而不是数据),即。在准备好的语句中使用 COUNT(*) 那么您所需要做的就是检索结果并读取值:

$sql = "SELECT count(*) FROM `table` WHERE foo = bar";
$statement = $con->prepare($sql); 
$statement->execute(); 
$count = $statement->fetch(PDO::FETCH_NUM); // Return array indexed by column number
return reset($count); // Resets array cursor and returns first value (the count)
Run Code Online (Sandbox Code Playgroud)

实际上检索所有行(数据)来执行简单的计数是浪费资源。如果结果集很大,您的服务器可能会卡住。