PHP Conference Japan 2024

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 时返回。

参数

此函数没有参数。

返回值

返回行数。

错误/异常

如果属性 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 "Return number of rows that were deleted:\n";
$count = $del->rowCount();
print
"Deleted $count rows.\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
"There are " . $count . " matching records.";

以上示例将输出类似以下内容

There are 2 matching records.

参见

添加注释

用户贡献的注释 13 条注释

89
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() 将告诉您更新查询实际找到/匹配了多少行。
42
Matt
17 年前
太好了,在使用 MySQL5 时,执行 PDO SELECT 查询后获取行数的唯一方法是执行单独的 SELECT COUNT(*) 查询(或执行 count($stmt->fetchAll()),这似乎是一种荒谬的开销和编程时间浪费)。

我对 PDO 的另一个抱怨是它无法在某些 DBMS(例如 SQL Server)中获取存储过程的输出参数的值。

我不确定我是否还喜欢 PDO。
33
Daniel Karp
12 年前
请注意,INSERT ... ON DUPLICATE KEY UPDATE 语句不是 INSERT 语句,对于此类语句,rowCount 不会返回插入或更新的行数。对于 MySQL,如果插入行,它将返回 1,如果更新行,它将返回 2,但这可能不适用于其他数据库。
25
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
'Empty Query';
}
?>
18
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();
?>
12
sERGE-01
11年前
在某些驱动程序中,rowCount() 仅在使用 PDO::CURSOR_SCROLL 的 prepare() 时有效。
因此,您可以修改 PDO 类。

<?php
class myPDO extends PDO
{
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
function TestRowCount($dsn, $db_user, $db_pass)
{
$pdh = new PDO($dsn, $db_user, $db_pass);
$sth = $pdh->query("SELECT * FROM sys.tables");
print
"rowCount() 标准: ".$sth->rowCount()."<br>";

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

$pdh=null;
}

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

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

print
"MSSQL 通过 PDO_ODBC"."<br>";
TestRowCount("odbc:DRIVER={SQL Server};SERVER=$db_server;DATABASE=$db_name;", $db_user, $db_pass);

print
"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%"));
?>
5
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
8
user at nospam dot example dot com
11年前
MySQL 似乎没有在 select 语句的 rowCount 中返回任何内容,但您可以轻松高效地获取行数,如下所示

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 "执行某些操作!";
}
2
info at buylikesandviews dot com
9年前
每一项好的工作
如果您使用“INSERT INTO ... ON DUPLICATE KEY UPDATE”语法,mysql_affected_rows() 将在进行更新时返回 2(就像“REPLACE INTO”语法一样)以及在插入时返回 1。

因此,如果您使用一个 SQL 请求一次插入多行,并且某些行被插入,某些行只是被更新,您将无法获得真实的计数。
1
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;
?>
0
bohwaz
5年前
请注意 PostgreSQL 的另一种有趣的行为。

如果您尝试在使用设置为 PDO::CURSOR_SCROLL 的 PDO::ATTR_CURSOR 准备语句后使用 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

此文档将很快更新以反映该问题。
-4
e dot sand at elisand dot com
16 年前
从 SQLite 3.x 版本开始,SQLite API 本身发生了变化,现在所有查询都使用“语句”来实现。因此,PDO 无法知道 SELECT 结果的 rowCount,因为 SQLite API 本身不提供此功能。

作为一种变通方法,我创建了自己的 rowCount() 函数——这有点像黑客手段,尚未完全测试(我不知道它在 SELECT 中使用 JOIN 时会如何工作等等),但至少可以避免在代码中到处使用 SELECT COUNT(*)。

我更希望能够重载 PDOStatement 中的 rowCount() 函数,但我认为这是不可能的(或者我不知道如何做到)。此外,还有可能需要更多的安全性,以确保在其他 query() 后清除 $queryString,这样你就不会得到错误的结果等等……

实际代码应该发布在上述/下面的帖子中(帖子长度限制,唉!)。如果其他人希望扩展/完善此方法,请通过电子邮件告诉我你做了什么。
-5
@rhavendc (twitter)
9年前
我们遇到了这些 PDOStatement::fetchColumn() 和 PDOStatement::rowCount() 的问题。我不知道我们是否与其他人有类似的情况,或者这仅仅是我们编码中的问题。在本地,rowCount() 没有给出正确的行数,但在上传到我们的托管站点时却可以正常工作……而 fetchColumn() 则相反。fetchColumn() 在本地工作正常,但上传后就不再正常了。我不知道到底发生了什么,但我认为 rowCount() 是最好的,其他的都是可选的。
To Top