mysql_num_rows

(PHP 4, PHP 5)

mysql_num_rows获取结果中的行数

警告

此扩展在 PHP 5.5.0 中已弃用,并在 PHP 7.0.0 中移除。应使用 MySQLiPDO_MySQL 扩展。另请参见 MySQL:选择 API 指南。此函数的替代方案包括

说明

mysql_num_rows(资源 $result): 整数|false

检索结果集中的行数。此命令仅对返回实际结果集的语句(如 SELECT 或 SHOW)有效。要检索 INSERT、UPDATE、REPLACE 或 DELETE 查询影响的行数,请使用 mysql_affected_rows()

参数

result

正在评估的结果 资源。此结果来自对 mysql_query() 的调用。

返回值

成功时为结果集中的行数,失败时为 false

示例

示例 #1 mysql_num_rows() 示例

<?php

$link
= mysql_connect("localhost", "mysql_user", "mysql_password");
mysql_select_db("database", $link);

$result = mysql_query("SELECT * FROM table1", $link);
$num_rows = mysql_num_rows($result);

echo
"$num_rows 行\n";

?>

注释

注意:

如果您使用 mysql_unbuffered_query(),则 mysql_num_rows() 不会返回正确的值,直到结果集中的所有行都被检索到。

注意:

为了向后兼容,可以使用以下已弃用的别名:mysql_numrows()

参见

添加注释

用户贡献的注释 22 个注释

sam at liddicott dot com
19 年前
关于此页面的一些用户评论,以及一些资源,包括位于

http://www.faqts.com/knowledge_base/view.phtml/aid/114/fid/12 的常见问题解答,建议使用 count(*) 来计算行数

这不是一个特别通用的解决方案,阅读此页面评论的人也应该知道

如果您的查询中使用“group by”或“having”,则 select count(*) 可能不会给出正确的结果,因为 count(*) 是一个聚合函数,每次 group-by 列更改时都会重置。

select sum(..) ... left join .. group by ... having ...

可以作为 mysql 3 中子查询的替代方案,并且此类查询不能将 select 字段替换为 count(*) 以给出良好的结果,它根本不起作用。

Sam
Joebomb
8 年前
回复上一条帖子:这可能并不总是能正确工作,因为 $object->doesExist 将包含结果,而不是布尔值。更好的方法(使用相同的方法)是使用强制转换

<?php
class Object {
var
$doesExist = false;

[...]
function
load() {
$result = mysql_query('...');
$this->doesExist = (bool) ($res = mysql_fetch_array($result))
[...]
}
}
?>
pjoe444 at yahoo dot com
19 年前
关于我的上一条条目

这似乎是让“普通”循环进行的最佳变通方法,并且可以根据行号更改输出
(例如布置时间表)

$rowno=mysql_num_rows($result);

for ($i=0; $i<mysql_num_rows($result); $i++) {
$row = mysql_fetch_assoc($result);

print "<div class=\"showing\">";
print "<b>".$row['timeon']."-".$row['timeoff']."</b> ".$row['event']."<br />;
if ($i!=$rowno-1) {
print "other-html-within-sched-here</div>";
}
else print "end-last-entry-html-here</div>";
} //关闭循环
aaronp123 att yahoo dott comm
21 年前
我可能是唯一一个遇到过这个问题的人 - 但是,如果您有一个包含一行的 myisam 表,并且您使用有效的表和列名称搜索结果,您可能期望有 0 行,您将不会得到 0,您将得到 1,这是 myisam 在表有 0 行或 1 行时的优化响应。在“5.2.4 MySQL 如何优化 WHERE 子句”中,它写道

*尽早检测无效的常量表达式。MySQL 会很快检测到某些 SELECT 语句是不可能的,并返回 0 行。



*所有常量表都在任何其他表之前读取。常量表是
1) 空表或包含 1 行的表。
2) 在唯一索引或主键上使用 WHERE 子句的表,其中所有索引部分都使用常量表达式,并且索引部分被定义为 NOT NULL。

希望这能让某些人免于彻夜与 1146 错误作斗争,除非我完全误解了我的想法。
philip at cornado dot c()m
23 年前
关于 SQL count(),请参阅此常见问题解答
* http://www.faqts.com/knowledge_base/view.phtml/aid/114/fid/12
注意:如果您已经有一个 $result,请对其使用 mysql_num_rows(),否则使用 SQL count()。不要仅仅为了计数而 SELECT 数据。
匿名
19 年前
回复 oran at trifeed dot com

您只会在没有为 FOUND_ROWS() 结果指定别名时才会遇到此行为

$qry = mysql_query ( 'SELECT FOUND_ROWS() AS total' );
$rst = mysql_fetch_array ( $qry, MYSQL_ASSOC );
echo $rst['total'];

Sean :)
Typer85 at gmail dot com
17 年前
关于以下用法的说明;建议使用多个 MySQL 函数来获取表记录的数量。

您可能熟悉以下内容

<?php

$sqlQuery
= 'Select SQL_CALC_FOUND_ROWS `MyField` From `MyTable` Limit 1;';

$sqlQuery_1 = 'Select FOUND_ROWS( );';

?>

我省略了实际连接到 MySQL 和执行查询的部分,但你应该能明白意思。

我进行了一些测试,在一个流量相当大的网站上,该网站经常执行多个查询,发现使用这种 MySQL 函数组合实际上会导致错误的结果。

例如,假设我有两个查询来获取两个不同表的表记录数量。因此,本质上,我们正在执行 4 个查询(每个表 2 个查询)。

如果两个不同的请求通过 PHP 传入,你就会遇到问题。请注意,当我说请求时,我的意思是两个不同的客户端请求你的 PHP 页面。

---------------
请求 1
---------------

执行:在表 1 上执行 SQL_CALC_FOUND_ROWS

---------------
请求 2
---------------

执行:在表 2 上执行 SQL_CALC_FOUND_ROWS

---------------
请求 1
---------------

执行:Select FOUND_ROWS( )

此时,你会看到发生的竞争条件。当请求 1 正在执行时,请求 2 传入。

此时,请求 1 将返回表 2 中的表记录数量,而不是预期的表 1 的记录数量!

为什么?因为 MySQL 不区分请求。每个查询都在队列中等待轮到它。一旦轮到它,它就会被 MySQL 执行。

MySQL 函数 Select FOUND_ROWS( ) 将返回最后一个 SQL_CALC_FOUND_ROWS 的结果!

请记住。
dzver at abv dot bg
19 年前
运行第二个查询“select count(...) from ... ”比在你的第一个查询中添加 SQL_CALC_FOUND_ROWS,然后使用 select FOUND_ROWS() + mysql_num_rows() 速度更快。
pjoe444 at yahoo dot com
19 年前
可惜似乎没有办法获取在典型循环中正在迭代的当前行号,
例如
while ($row = mysql_fetch_assoc($result)) { }

毕竟有一个行数组数组,如
mysql_num_rows($result)

假设这给出“40 行”:知道迭代在第 39 行时会很有用。

最接近的似乎是“数据查找”:但它直接连接到
行号,例如(来自 mysql_data_seek 页面)

for ($i = mysql_num_rows($result) - 1; $i >= 0; $i--) {
if (!mysql_data_seek($result, $i)) {
echo "Cannot seek to row $i: " . mysql_error() . "\n";
continue;
}

= 它仍然无法解决在普通循环中知道你所在的行号的问题。

这种情况的一个原因是 php fetch(获取单行)构造,没有与行号相关的合理的 FOR 循环可能性。

建议
$Rows[$i] 可能性,其中
$i 将是行号

$Rows[$row[], $row[], $row[].....]
0 1 2 等

-- 行内出色的检索($row[$i]),
虽然当然更重要,但没有与
行本身的类似可能性相匹配。

当然,Count($result) 不起作用,$result 只是一个
票证标识符...

Peter T
gtaylor at sonic dot net
15 年前
在防止 SQL_CALC_FOUND_ROWS 和 FOUND_ROWS() 操作的竞争条件方面,将 FOUND_ROWS() 结果包含在实际结果集中可能会变得复杂且有些笨拙,尤其对于复杂的查询和/或结果排序。查询变得更加复杂,你可能难以隔离/排除 FOUND_ROWS() 结果,而且 mysql_num_rows() 将返回实际结果数量 + 1,所有这些都使你的代码更混乱且更难阅读。但是,竞争条件是真实存在的,必须处理。

一种更简洁、更干净的方法是使用 WRITE 锁显式锁定表(防止其他进程读取/写入该表)。我能看到的缺点是性能下降,并且你的 mysql 用户必须具有锁定权限。

<?php
// excuse the use of mysqli instead of mysql

$mysqli->query("LOCK TABLE t WRITE");
$results = $mysqli->query("SELECT id FROM t LIMIT 0,10");
$totalNumResults = array_pop($mysqli->query("SELECT FOUND_ROWS()")->fetch_row());
$mysqli->query("UNLOCK TABLES");
?>

现在你可以像迭代其他结果集一样迭代结果。
oran at trifeed dot com
19 年前
对我来说

SELECT SQL_CALC_FOUND_ROWS 与
SELECT FOUND_ROWS()

仅在以下语法下有效
$result = @mysql_query($query);
$resultTotal = @mysql_query("SELECT FOUND_ROWS()");
$res= mysql_fetch_array($resultTotal);
echo $res['FOUND_ROWS()'];

希望有帮助

oran
http://www.trifeed.com
Typer85 at gmail dot com
14 年前
实际上,我有点不好意思说这话,但我必须纠正我在 2007 年 7 月 17 日 06:44 发布的一条非常旧的笔记。

使用 SQL_CALC_FOUND_ROWS 和 FOUND_ROWS( ) 不会在 MySQL 上触发竞争条件,因为这几乎违背了它们整个目的。

它们的使用结果实际上对于每个连接会话都是唯一的,因为进程无法在 PHP 中共享任何内容。就 PHP 而言,每个请求都代表与 MySQL 的新连接,因为每个请求都独立于其自身进程。

要模拟这种情况,请创建以下脚本

<?php

$Handle
= mysql_connect( "localhost" , "root" , "" );
mysql_select_db( "lls" );

if( isset(
$_GET[ 'Sleep' ] ) ) {
mysql_query( "SELECT SQL_CALC_FOUND_ROWS `bid` From `blocks` Limit 1" );
} else {
mysql_query( "SELECT SQL_CALC_FOUND_ROWS `aid` From `access` Limit 1" );
}

if( isset(
$_GET[ 'Sleep' ] ) ) {
sleep( 10 ); // Simulate another HTTP request coming in.
$Result = mysql_query( "SELECT FOUND_ROWS( )" );
print_r( mysql_fetch_array( $Result ) );
}

mysql_close( );

?>

设置与你的环境匹配的连接和查询信息。

使用 Sleep 查询字符串运行一次脚本,再运行一次不使用 Sleep 查询字符串。重要的是同时运行它们。使用 Apache ab 或类似工具,甚至更简单,只需打开两个浏览器标签即可。例如

http://localhost/Script.php?Sleep=10
http://localhost/Script.php

如果存在竞争条件,第一个脚本实例的结果将等于第二个脚本实例的结果。

例如,第二个脚本实例将执行以下 SQL 查询

<?php

mysql_query
( "SELECT SQL_CALC_FOUND_ROWS `aid` From `access` Limit 1" );

?>

当第一个脚本实例休眠时,这会发生。如果存在竞争条件,当第一个脚本实例醒来时,它执行的 FOUND_ROWS( ) 的结果应该是第二个脚本实例执行的 SQL 查询中的行数。

但是当你运行它们时,情况并非如此。第一个脚本实例返回其自身查询的行数,即

<?php

mysql_query
( "SELECT SQL_CALC_FOUND_ROWS `bid` From `blocks` Limit 1" );

?>

因此事实证明,不存在竞争条件,并且所有为解决此“问题”而提出的解决方案实际上都不需要。

祝你好运,
wil1488 at gmail dot com
19 年前
要使用 SQL COUNT 函数,但不选择源...

看一个例子

<?
//与数据库建立连接

$my_table = mysql_query("SELECT COUNT(*) as TOTALFOUND from table", $link); //执行 SQL 代码
注意:将返回 TOTALFOUND 中的总数

print (mysql_result($my_table,0,"TOTALFOUND")); //使用字段营地从你的 SQL 查询中获取总数!
?>

谢谢,祝你好运。
tac at smokescreen dot org
22 年前
MySQL 4.0 支持一项很棒的新功能,它允许你获取如果查询没有 LIMIT 子句,将返回的行数。要使用它,你需要在查询中添加 SQL_CALC_FOUND_ROWS,例如

$sql = "Select SQL_CALC_FOUND_ROWS * from table where state='CA' limit 50";
$result = mysql_query($sql);

$sql = "Select FOUND_ROWS()";
$count_result = mysql_query($sql);

你现在拥有与条件匹配的表中的总行数。这对于在浏览列表时了解总记录数非常有用。
webmaster dasourcerer net
16 年前
在我的一个应用程序中,我必须让一个对象知道它是否存在于数据库中。我发现了一个无需使用 mysql_num_rows() 的廉价解决方案

<?php
class Object {
var
$doesExist = false;

[...]
function
load() {
$result = mysql_query('...');
$this->doesExist = ($res = mysql_fetch_array($result))
[...]
}
}
?>
simon_nuttall at hotmail dot com
18 年前
wil1488 at gmail dot com 评论中面向对象的版本,用于计算表行
<?php
$result
= $mysqli->query("SELECT COUNT(*) as TOTALFOUND from table");
$row_array=$result->fetch_array(MYSQLI_ASSOC);
print(
$row_array['TOTALFOUND']);
?>
Tom Fejfar
16 年前
对 chrisdberry82 at gmail dot com 代码的改进

<?php
$sql
= "
SELECT SQL_CALC_FOUND_ROWS
'0', z.id
FROM
zoom AS z
LIMIT
0,6
UNION
SELECT
'1', FOUND_ROWS()
ORDER BY `0` DESC , RAND()"
;
?>

您可以看到,您甚至可以按照您喜欢的任何方式对最终结果进行排序;)
然后您可以像这样获取结果
<?php
$res
= mysql_query($sql);
$count = mysql_fetch_assoc($res);
while(
$row = mysql_fetch_assoc($res)){
unset(
$row["0"]); //get rid of the "sorting col"
print_r($row); //or whatever ;)
}
echo
$count["id"]; // the total number of rows
?>

并且您摆脱了糟糕的 IF 语句;)
mauriciocramos at gmail dot com
13 年前
当 mysql.trace_mode = On 时,SELECT FOUND_ROWS() 总是返回 0。这看起来像是一个错误。

详细说明

如果您有一个包含 5 行的表,并发出

SELECT SQL_CALC_FOUND_ROWS * FROM table LIMIT 1;

mysql_num_rows() 按预期返回 1。

如果您按顺序在同一个连接资源中发出 "SELECT FOUND_ROWS()",它总是返回 0,而不是预期的 5。

只需将 mysql.trace_mode 切换到 Off,一切就会正常工作。
chrisdberry82 at gmail dot com
16 年前
以下代码可以将所有内容封装到一个查询中,这样您就不必担心多个客户端请求

$stmtMain = $mysqli->prepare("SELECT SQL_CALC_FOUND_ROWS jobid,title FROM tbljobs
LIMIT ?, ? UNION SELECT FOUND_ROWS(),'!!IgnoreCount!!';")

然后使用类似以下内容迭代结果

while ($stmtMain->fetch() && $strResultTitle !="!!IgnoreCount!!") {
//do stuff
}
($strResultSector == '!!IgnoreCount!!')? $intTotal = $intResultCount : 1;
deaggi at deaggi dot net
16 年前
回复上一条帖子:这可能并不总是能正确工作,因为 $object->doesExist 将包含结果,而不是布尔值。更好的方法(使用相同的方法)是使用强制转换

<?php
class Object {
var
$doesExist = false;

[...]
function
load() {
$result = mysql_query('...');
$this->doesExist = (bool) ($res = mysql_fetch_array($result))
[...]
}
}
?>

约翰内斯
timo
16 年前
<?
$strQuery="SELECT * FROM `tabel`";
$strResult = mysql_query($strQuery);
$Aantalvelden = mysql_num_fields($strResult);
$Aantalrijen=mysql_num_rows($strResult);

echo "<table border='1'><tr>";
for($ikolom=0;$ikolom<$Aantalvelden;$ikolom++){
$strVeldnaam = mysql_field_name($strResult,$ikolom);
echo "<td>$strVeldnaam</td>" ;
}
echo "</tr>";

for($ir=0;$irij<$Aantalrijen;$irij++){
echo "<tr>";
for($ikolom=0;$ikolom<$Aantalvelden;$ikolom++){
$strKolomwaarde = mysql_result($strResult,$irij,$ikolom);
echo "<td>$strKolomwaarde</td>";
}
}
echo "</table>";
?>
Jonas
18 年前
关于 SQL_CALC_FOUND_ROWS 和 FOUND_ROWS() 的一个小提示

请记住,您可以在使用 mysql_fetch_assoc 时使用 "AS"。

$sql="
SELECT
FOUND_ROWS() AS `found_rows`;
";
$result = mysql_query($sql);
$myrow = mysql_fetch_assoc($result);
$row_count = $myrow['found_rows'];

echo $row_count;
To Top