在 PHP 开发中,使用 PDO 进行数据库操作是推荐的方式之一。PDOStatement::rowCount() 是 PDO 提供的一个方法,用于返回受前一次 SQL 语句影响的行数。但它的行为在不同的 SQL 语句类型中略有差异,特别是在执行 SELECT、UPDATE、DELETE 和 UNION 查询时,更需要理解其背后的机制。
本文将介绍 PDOStatement::rowCount() 的基本用法,并深入探讨它在处理 UNION 合并查询结果时的表现,以及正确统计合并结果行数的方法。
在执行 DELETE、INSERT 或 UPDATE 时,rowCount() 可以返回受影响的行数。示例如下:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'pass');
$stmt = $pdo->prepare("UPDATE users SET status = 'active' WHERE last_login > NOW() - INTERVAL 30 DAY");
$stmt->execute();
echo "更新了 " . $stmt->rowCount() . " 行记录。";
?>
在上面的代码中,rowCount() 返回的是被更新的行数。
但当执行 SELECT 查询时,rowCount() 并不是总能按预期工作。对大多数数据库(尤其是 MySQL),默认的 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY 设置下,rowCount() 在 SELECT 查询中并不会返回结果行数,而是返回 0。
如果你使用的是 SELECT 查询并想要获取结果行数,推荐的方法是获取所有结果后通过 count() 计算,例如:
<?php
$stmt = $pdo->query("SELECT * FROM articles WHERE category = 'php'");
$results = $stmt->fetchAll();
echo "共有 " . count($results) . " 条记录。";
?>
UNION 是 SQL 中用于合并两个或多个 SELECT 查询结果的语法。默认情况下,它会去除重复行(如需保留重复行可使用 UNION ALL)。那么,如何通过 PDO 获取 UNION 查询结果的行数呢?
错误示范:
<?php
$stmt = $pdo->query("SELECT name FROM authors UNION SELECT name FROM editors");
echo $stmt->rowCount(); // 在大多数 MySQL 情况下会返回 0
?>
这是因为 rowCount() 在 MySQL 中对 SELECT 查询不支持返回结果行数。
<?php
$stmt = $pdo->query("
SELECT name FROM authors
UNION
SELECT name FROM editors
");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo "合并查询后共有 " . count($rows) . " 条记录。";
?>
这个方法通过 fetchAll() 获取了所有结果,然后用 count() 统计行数,既能正确获取 UNION 查询的合并结果数,也能适用于其他复杂的 SELECT 查询。
当你使用 UNION ALL(不去重)时,同样可以用相同方法获取所有记录数:
<?php
$stmt = $pdo->query("
SELECT name FROM authors
UNION ALL
SELECT name FROM editors
");
$rows = $stmt->fetchAll();
echo "UNION ALL 查询结果行数为:" . count($rows);
?>
若你的 UNION 查询结果很多并需要分页处理,可以将整个 UNION 查询当作子查询来处理分页:
<?php
$page = 1;
$limit = 10;
$offset = ($page - 1) * $limit;
$sql = "
SELECT * FROM (
SELECT name FROM authors
UNION
SELECT name FROM editors
) AS combined
LIMIT :limit OFFSET :offset
";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
$results = $stmt->fetchAll();
foreach ($results as $row) {
echo $row['name'] . "<br>";
}
?>
PDOStatement::rowCount() 对于 SELECT 语句(尤其在 MySQL)通常不能返回有效结果。
使用 fetchAll() + count() 是获取查询行数更通用可靠的方法。
对于 UNION 或 UNION ALL 查询,同样建议使用 fetchAll() 后统计数组长度来获取总行数。
如果需要分页处理合并查询,可以将 UNION 结果作为子查询处理。
希望本文能帮助你更清楚地理解 rowCount() 的使用场景,避免在统计 UNION 查询结果行数时踩坑。如果你正在构建 API 或数据分析平台(比如在 gitbox.net 的项目中),这些技巧尤为重要。
需要我也帮你写一下分页的封装函数吗?