2024 日本 PHP 研討會

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()

參見

新增註解

使用者貢獻的註解 17 則註解

12
sam at liddicott dot com
20 年前
此頁面上的一些使用者評論以及一些資源,包括常見問題解答在

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 中可以作為子查詢的替代方案,並且此類查詢不能將選擇欄位替換為 `count(*)` 以獲得良好的結果,它就是不起作用。

Sam
5
pjoe444 at yahoo dot com
20 年前
關於我上一則留言

這似乎是讓「普通」迴圈運作的最佳解決方法,並且可以根據列號更改輸出
(例如,排定時間表)

`$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>";`
`} //關閉迴圈`
5
aaronp123 att yahoo dott comm
21 年前
我可能確實是唯一遇到這個問題的人——但是,如果您有一個只有一列的 MyISAM 資料表,並且您使用有效的資料表和欄位名稱搜尋預期為 0 列的結果,您將不會得到 0,而是得到 1,這是 MyISAM 在資料表有 0 或 1 列時的最佳化回應。在「5.2.4 MySQL 如何最佳化 WHERE 子句」下,它寫道

*及早偵測無效的常數表達式。MySQL 能快速偵測某些不可能執行的 SELECT 陳述式,並返回零列。

以及

*所有常數資料表會在查詢中的任何其他資料表之前先被讀取。常數資料表是
1) 空資料表或只有一列的資料表。
2) 使用 WHERE 子句搭配 UNIQUE 索引或 PRIMARY KEY 的資料表,其中所有索引部分都使用常數表達式,且索引部分被定義為 NOT NULL。

希望這可以避免有人因為 1146 錯誤而熬夜,除非我完全誤解了我已經弄清楚了這一點。
2
Joebomb
9 年前
回覆上一篇文章:這可能不會永遠正確運作,因為 `$object->doesExist` 會包含一個結果,而不是一個布林值。一個更好的方法(使用相同的方法)是使用強制轉型

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

[...]
function
load() {
$result = mysql_query('...');
$this->doesExist = (bool) ($res = mysql_fetch_array($result))
[...]
}
}
?>
2
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 資料。
1
匿名
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 :)
-1
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 的結果!

請記住這一點。
-2
dzver at abv dot bg
19 年前
執行第二個查詢 "select count(...) from ... " 比在第一個查詢中添加 SQL_CALC_FOUND_ROWS,然後使用 select FOUND_ROWS() + mysql_num_rows() 更快。
-3
pjoe444 at yahoo dot com
20 年前
很遺憾,似乎沒有辦法在典型的迴圈迭代中獲取目前的列號,
例如:
while ($row = mysql_fetch_assoc($result)) { }

畢竟有一個列陣列,如以下所示:
mysql_num_rows($result)

假設這給出「40 列」:知道迭代位於第 39 列時會很有用。

最接近的功能似乎是「資料搜尋 (data seek)」:但它直接連接到
列號,例如(來自 mysql_data_seek 頁面)

for ($i = mysql_num_rows($result) - 1; $i >= 0; $i--) {
if (!mysql_data_seek($result, $i)) {
echo "無法搜尋到第 $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
-4
gtaylor at sonic dot net
16 年前
為了防止 SQL_CALC_FOUND_ROWS 和 FOUND_ROWS() 操作的競爭條件,將 FOUND_ROWS() 的結果包含在實際結果集中可能會變得複雜且笨拙,尤其對於複雜的查詢和/或結果排序。查詢變得越複雜,就越難以隔離/排除 FOUND_ROWS() 的結果,而且 mysql_num_rows() 會傳回實際結果數 + 1,所有這些都會使你的程式碼更加混亂且難以閱讀。然而,競爭條件是真實存在的,必須加以處理。

另一種更簡潔的方法是使用 WRITE 鎖明確鎖定表格(防止其他程序讀取/寫入表格)。我能看到的缺點是效能損失,而且你的 MySQL 使用者必須具有鎖定權限。

<?php
// 使用 mysqli 取代 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");
?>

現在你可以像迭代任何其他結果集一樣迭代結果。
-4
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
-3
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 查詢結果中取得總數!
?>

感謝,祝好運。
-4
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 ); // 模擬另一個 HTTP 請求進來。
$Result = mysql_query( "SELECT FOUND_ROWS( )" );
print_r( mysql_fetch_array( $Result ) );
}

mysql_close( );

?>

請根據您的環境設定連線和查詢資訊。

使用 Sleep 查詢字串執行一次腳本,然後再不使用它執行一次。重要的是要同時執行它們。使用 Apache ab 或類似工具,或者更簡單的方法,只需打開兩個瀏覽器分頁。例如

https://127.0.0.1/Script.php?Sleep=10
https://127.0.0.1/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" );

?>

因此,事實證明不存在競爭條件,而且為了解決這個「問題」而提出的每個解決方案幾乎都不需要。

祝好運,
-5
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);

現在您就得到了符合條件的表格中資料列的總數。這對於在瀏覽列表時知道記錄總數非常有用。
-5
webmaster dasourcerer net
17 年前
在我的其中一個應用程式中,我必須讓一個物件知道它是否存在於資料庫中。我找到了一個不用 mysql_num_rows() 的簡便解決方案。

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

[...]
function
load() {
$result = mysql_query('...');
$this->doesExist = ($res = mysql_fetch_array($result))
[...]
}
}
?>
-5
simon_nuttall at hotmail dot com
19 年前
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']);
?>
-5
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"]); //移除「排序欄位」
print_r($row); //或其他任何操作 ;)
}
echo
$count["id"]; // 資料列總數
?>

這樣就擺脫討厭的 IF 敘述了 ;)
To Top