2024 年日本 PHP 研討會

PDOStatement::rowCount

(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.1.0)

PDOStatement::rowCount 傳回受最後一個 SQL 陳述式影響的列數

說明

public PDOStatement::rowCount(): int

PDOStatement::rowCount() 會傳回受對應 PDOStatement 物件執行的最後一個 DELETE、INSERT 或 UPDATE 陳述式影響的列數。

對於產生結果集的陳述式,例如 SELECT,其行為未定義,且可能因各個驅動程式而異。某些資料庫可能會傳回該陳述式產生的列數(例如緩衝模式下的 MySQL),但並非所有資料庫都保證會有此行為,因此可攜式應用程式不應依賴此行為。

注意:

這個方法在使用 SQLite 驅動程式時總是會回傳「0」(零),而使用 PostgreSQL 驅動程式時,只有在將PDO::ATTR_CURSOR 陳述式屬性設定為 PDO::CURSOR_SCROLL 時才會回傳「0」。

參數

這個函式沒有參數。

回傳值

回傳資料列的數量。

錯誤/例外

如果屬性 PDO::ATTR_ERRMODE 設定為 PDO::ERRMODE_WARNING,則會發出層級為 E_WARNING 的錯誤。

如果屬性 PDO::ATTR_ERRMODE 設定為 PDO::ERRMODE_EXCEPTION,則會擲出 PDOException 例外。

範例

範例 #1 回傳已刪除資料列的數量

PDOStatement::rowCount() 會回傳受 DELETE、INSERT 或 UPDATE 陳述式影響的資料列數量。

<?php
/* 從 FRUIT 資料表刪除所有資料列 */
$del = $dbh->prepare('DELETE FROM fruit');
$del->execute();

/* 回傳已刪除的資料列數量 */
print "回傳已刪除的資料列數量:\n";
$count = $del->rowCount();
print
"已刪除 $count 列資料。\n";
?>

上述範例會輸出類似以下的內容

Return number of rows that were deleted:
Deleted 9 rows.

範例 #2 計算 SELECT 陳述式回傳的資料列數量

對於大多數資料庫,PDOStatement::rowCount() 不會回傳受 SELECT 陳述式影響的資料列數量。請改用 PDO::query() 發出一個與您預期的 SELECT 陳述式具有相同述詞的 SELECT COUNT(*) 陳述式,然後使用 PDOStatement::fetchColumn() 來擷取相符資料列的數量。

<?php
$sql
= "SELECT COUNT(*) FROM fruit WHERE calories > 100";
$res = $conn->query($sql);
$count = $res->fetchColumn();

print
"共有 " . $count . " 筆相符的記錄。";

上述範例會輸出類似以下的內容

There are 2 matching records.

另請參閱

新增註記

使用者貢獻的註記 13 則註記

Ome Ko
13 年前
當使用相同的值更新 MySQL 資料表時,實際上沒有任何影響,因此 rowCount 將會返回 0。如同下方 Perl 先生所述,這並非總是預期的行為,您可以從 PHP 5.3 開始自行更改。

只需使用以下方式建立您的 PDO 物件
<? php
$p = new PDO($dsn, $u, $p, array(PDO::MYSQL_ATTR_FOUND_ROWS => true));
?>
rowCount() 就會告訴您更新查詢實際找到/符合的資料列數。
Matt
17 年前
太好了,使用 MySQL5 時,在執行 PDO SELECT 查詢後取得資料列數的唯一方法是執行另一個獨立的 SELECT COUNT(*) 查詢(或者執行 count($stmt->fetchAll()),這看起來像是對系統資源和程式設計時間的荒謬浪費)。

我對 PDO 的另一個抱怨是它無法從某些 DBMS(例如 SQL Server)的預存程序中取得輸出參數的值。

我不太確定我是否喜歡 PDO。
Daniel Karp
12 年前
請注意,INSERT ... ON DUPLICATE KEY UPDATE 陳述式並非 INSERT 陳述式,rowCount 不會返回此類陳述式插入或更新的資料列數。對於 MySQL,如果插入資料列,它會返回 1,如果更新資料列,則返回 2,但这可能不適用於其他資料庫。
leandro at marquesini dot com
12 年前
為了只在查詢不為空時顯示資訊,我會這樣做

<?php
$sql
= 'SELECT model FROM cars';
$stmt = $db->prepare($sql);
$stmt->execute();

if (
$data = $stmt->fetch()) {
do {
echo
$data['model'] . '<br>';
} while (
$data = $stmt->fetch());
} else {
echo
'空的查詢';
}
?>
gunnrosebutpeace at gmail dot com
16 年前
如果只使用 MySQL,最好使用 SQL_CALC_FOUND_ROWS。它有很多優點,您可以只擷取部分結果集(透過 LIMIT),但仍然可以取得總資料列數。
程式碼
<?php
$db
= new PDO(DSN...);
$db->setAttribute(array(PDO::MYSQL_USE_BUFFERED_QUERY=>TRUE));
$rs = $db->query('SELECT SQL_CALC_FOUND_ROWS * FROM table LIMIT 5,15');
$rs1 = $db->query('SELECT FOUND_ROWS()');
$rowCount = (int) $rs1->fetchColumn();
?>
sERGE-01
11 年前
在某些驅動程式中,`rowCount()` 只有在使用 `prepare()` 搭配 `PDO::CURSOR_SCROLL` 時才能正常運作。
因此,您可以修改 PDO 類別:

<?php
class myPDO extends PDO
{
public function
query($query, $values=null)
{
if(
$query == "")
return
false;

if(
$sth = $this->prepare($query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL)))
{
$res = ($values) ? $sth->execute($values) : $sth->execute();
if(!
$res)
return
false;
}
return
$sth;
}
}
?>

現在讓我們測試一下(我使用的是 php 5.2.9-2)

<?php
函式 TestRowCount($dsn, $db_user, $db_pass)
{
$pdh = new PDO($dsn, $db_user, $db_pass);
$sth = $pdh->query("SELECT * FROM sys.tables");
顯示
"rowCount() 標準: ".$sth->rowCount()."<br>";

$pdh = new myPDO($dsn, $db_user, $db_pass);
$sth = $pdh->query("SELECT * FROM sys.tables");
顯示
"rowCount() 新方法: ".$sth->rowCount()."<br><br>";

$pdh=null;
}

$db_server = "xxx";
$db_name = "xxx";
$db_user = "xxx";
$db_pass = "xxx";

顯示
"PDO_MSSQL"."<br>";
TestRowCount("mssql:host=$db_server;dbname=$db_name", $db_user, $db_pass);

顯示
"MSSQL 透過 PDO_ODBC"."<br>";
TestRowCount("odbc:DRIVER={SQL Server};SERVER=$db_server;DATABASE=$db_name;", $db_user, $db_pass);

顯示
"MS SQL 驅動程式 2.0"."<br>";
TestRowCount("sqlsrv:server=$db_server;Database=$db_name", $db_user, $db_pass);
?>

我的結果
-------------------
PDO_MSSQL
rowCount() 標準: 0
rowCount() 新方法: 0

MSSQL 透過 PDO_ODBC
rowCount() 標準: -1
rowCount() 新方法: 53

MS SQL 驅動程式 2.0
rowCount() 標準: -1
rowCount() 新方法: 53
-------------------

使用 myPDO 類別,您可以使用準備好的查詢,例如
<?php
$pdh
= new myPDO($dsn, $db_user, $db_pass);
$sth = $pdh->query("select * from data where id>? or name like ?", array(100, "A%"));
?>
xmt at abv dot bg
6 年前
注意
=====
在使用緩衝查詢的 MySQL SELECT 語句中,rowCount 會返回結果集中正確的項目數量。
但如果您的查詢是非緩衝的,則它會返回 0。無論是否已從結果集中檢取所有列(而在 mysqli 中,此行為有所不同 - 您仍然可以使用非緩衝查詢獲取結果集中的項目數量,但僅當您從集合中檢取所有列時)。

範例
========
$conn = new PDO("mysql:host=127.0.0.1;dbname=db", 'root', 'root');

// 使用非緩衝查詢
$conn->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

$stmt = $conn->query("select * from towns");

echo $stmt->rowCount(); // 總是返回 0
user at nospam dot example dot com
11 年前
MySQL 似乎沒有在 rowCount 中為 select 語句返回任何內容,但您可以輕鬆有效地獲取列數,如下所示

class db extends PDO {
public function last_row_count() {
return $this->query("SELECT FOUND_ROWS()")->fetchColumn();
}
}

$myDb = new db('mysql:host=myhost;dbname=mydb', 'login', 'password' );

然後,在執行查詢後

if ( $myDb->last_row_count() == 0 ) {
echo "做一些事情!";
}
info at buylikesandviews dot com
9 年前
每一項好的工作
如果您使用「INSERT INTO ... ON DUPLICATE KEY UPDATE」語法,如果執行 UPDATE,mysql_affected_rows() 將返回 2(就像使用「REPLACE INTO」語法一樣),如果執行 INSERT,則返回 1。

因此,如果您使用一個 SQL 請求一次插入多行,並且有些被插入,有些只是被更新,您將無法獲得真實的計數。
lsrzj at facebook
8 年前
嗯,我不建議查詢兩次資料庫來獲取計數,然後再獲取我想要的數據。查詢一次並同時檢索記錄計數和數據本身會更簡單,並且效能更好

<?php
$sql
= "SELECT * FROM fruit WHERE calories > :calories";
$sth = $conn->prepare($sql);
$sth->bindParam(':calories', 100, PDO::PARAM_INT);
$res = $sth->execute();
if (
$res) {
$record = $sth->fetchAll();
/* 檢查符合 SELECT 陳述式列數 */
if (count($record) > 0) {
foreach (
$record as $row) {
print
"名稱: " . $row['NAME'] . "\n";
}
}
/* 沒有符合的列 -- 執行其他操作 */
else {
print
"沒有符合查詢的列。";
}
}
$conn = null;
?>
bohwaz
5 年前
請注意 PostgreSQL 的另一個有趣行為。

如果您嘗試在使用 PDO::ATTR_CURSOR 設定為 PDO::CURSOR_SCROLL 的情況下準備陳述式後使用 rowCount(),您將始終得到零 (0)。

這是因為 PG 無法得知游標中有多少列,直到它迭代完所有列。

<?php
$st
= $pdo->prepare('SELECT NOW();', [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
$st->execute();
var_dump($st->rowCount());
?>

將返回「0」,而沒有 CURSOR_SCROLL 屬性的相同陳述式將正確返回 1。

有關詳細資訊,請參閱此錯誤報告 https://bugs.php.net/bug.php?id=77855

此文件應很快更新以反映該問題。
e dot sand at elisand dot com
16 年前
從 SQLite 3.x 開始,SQLite API 本身發生了變化,現在所有查詢都使用「陳述式」來實現。因此,PDO 無法得知 SELECT 結果的 rowCount,因為 SQLite API 本身不提供此功能。

作為一種解決方法,我建立了自己的 rowCount() 函數 - 這有點像是一種 hack,尚未經過完整測試(我不知道在 SELECT 中使用 JOIN 時它會如何運作等等),但至少減輕了在程式碼中到處使用 SELECT COUNT(*) 的必要性。

我比較希望可以覆寫 PDOStatement 的 rowCount() 函式,但我想這應該是不可能的(或者我不知道該怎麼做)。另外,為了安全性起見,最好在執行其他 query() 之後,將 $queryString 清空,以避免產生錯誤的結果等等……

實際的程式碼應該會貼在上面/下面的文章中(最大文章篇幅限制,唉!)。如果其他人想要擴充/完善這個方法,請透過電子郵件讓我知道你們做了哪些修改。
@rhavendc (Twitter)
9 年前
我們在使用 PDOStatement::fetchColumn() 和 PDOStatement::rowCount() 時遇到問題。我不確定其他人是否也遇到類似的情況,或者這只是我們程式碼的問題。在本地端,rowCount() 無法取得正確的資料列數,但在上傳到我們的虛擬主機後卻正常運作;而 fetchColumn() 則相反,在本地端正常運作,但上傳後就不行了。我不知道實際上發生了什麼事,但我認為 rowCount() 是最好的方法,其他方法則是可選的。
To Top