当前位置: 首页> 最新文章列表> 如何使用 PDOStatement::rowCount 获取合并查询的结果

如何使用 PDOStatement::rowCount 获取合并查询的结果

gitbox 2025-05-28

在 PHP 开发中,使用 PDO 进行数据库操作是推荐的方式之一。PDOStatement::rowCount() 是 PDO 提供的一个方法,用于返回受前一次 SQL 语句影响的行数。但它的行为在不同的 SQL 语句类型中略有差异,特别是在执行 SELECTUPDATEDELETEUNION 查询时,更需要理解其背后的机制。

本文将介绍 PDOStatement::rowCount() 的基本用法,并深入探讨它在处理 UNION 合并查询结果时的表现,以及正确统计合并结果行数的方法。

一、PDOStatement::rowCount() 的基本用法

在执行 DELETEINSERTUPDATE 时,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 查询中正确获取结果行数

如果你使用的是 SELECT 查询并想要获取结果行数,推荐的方法是获取所有结果后通过 count() 计算,例如:

<?php
$stmt = $pdo->query("SELECT * FROM articles WHERE category = 'php'");
$results = $stmt->fetchAll();

echo "共有 " . count($results) . " 条记录。";
?>

三、使用 UNION 查询时的行数问题

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 查询不支持返回结果行数。

正确方法:fetchAll + count

<?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 时获取行数

当你使用 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 查询结果很多并需要分页处理,可以将整个 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() 是获取查询行数更通用可靠的方法。

  • 对于 UNIONUNION ALL 查询,同样建议使用 fetchAll() 后统计数组长度来获取总行数。

  • 如果需要分页处理合并查询,可以将 UNION 结果作为子查询处理。

希望本文能帮助你更清楚地理解 rowCount() 的使用场景,避免在统计 UNION 查询结果行数时踩坑。如果你正在构建 API 或数据分析平台(比如在 gitbox.net 的项目中),这些技巧尤为重要。

需要我也帮你写一下分页的封装函数吗?