PHP PDO扩展是操作数据库的安全高效方式,其中fetch和fetchAll都是PDOStatement类提供的用于获取查询结果的方法,但两者的工作逻辑和适用场景有明显区别。

方法基本定义
fetch方法用于从结果集中获取下一行数据,每次调用只会返回一条记录,内部会维护结果集的指针,调用后会自动移动到下一条记录。
fetchAll方法会一次性获取结果集中的所有剩余记录,返回一个包含所有行的数组,调用后结果集指针会移动到末尾。
核心区别对比
| 对比维度 | fetch | fetchAll |
|---|---|---|
| 返回结果 | 单条记录,无更多数据时返回false | 包含所有记录的数组,无数据时返回空数组 |
| 内存占用 | 每次只加载一条数据,内存占用低 | 一次性加载所有数据,数据量大时内存占用高 |
| 指针移动 | 每次调用移动一次指针 | 调用一次直接移动到末尾 |
| 适用场景 | 数据量大、需要逐行处理、流式读取的场景 | 数据量小、需要一次性获取所有数据处理的场景 |
参数说明
两个方法都支持传入fetch_style参数来指定返回数据的格式,常用的取值有:
PDO::FETCH_ASSOC:返回关联数组,键名为字段名PDO::FETCH_NUM:返回索引数组,键名为字段索引PDO::FETCH_BOTH:同时返回关联数组和索引数组,默认取值PDO::FETCH_OBJ:返回匿名对象,属性对应字段名
代码示例
fetch 使用示例
逐行获取用户表数据并打印:
<?php
try {
// 创建PDO连接
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8', 'root', '123456');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 执行查询
$stmt = $pdo->query('SELECT id, name, age FROM users');
// 逐行获取数据处理
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo "用户ID:{$row['id']},姓名:{$row['name']},年龄:{$row['age']}<br>";
}
} catch (PDOException $e) {
echo "数据库操作失败:{$e->getMessage()}";
}
?>
fetchAll 使用示例
一次性获取所有用户数据后批量处理:
<?php
try {
// 创建PDO连接
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test;charset=utf8', 'root', '123456');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 执行查询
$stmt = $pdo->query('SELECT id, name, age FROM users LIMIT 10');
// 一次性获取所有数据
$allUsers = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 批量处理数据
foreach ($allUsers as $user) {
echo "用户ID:{$user['id']},姓名:{$user['name']}<br>";
}
// 可以再次查看结果集,此时已经没有数据了
$nextRow = $stmt->fetch(PDO::FETCH_ASSOC);
var_dump($nextRow); // 输出false
} catch (PDOException $e) {
echo "数据库操作失败:{$e->getMessage()}";
}
?>
使用注意事项
如果查询结果集数据量很大,比如超过几万条,不建议使用fetchAll,否则会占用大量内存甚至导致内存溢出,此时应该使用fetch逐行处理。如果数据量很小,比如几十条以内,使用fetchAll可以简化代码逻辑,减少循环调用的开销。
另外调用fetchAll之后,结果集的指针已经到末尾,再次调用fetch只会返回false,如果需要重复使用结果集,可以在调用fetchAll之前用PDOStatement::fetchAll(PDO::FETCH_ASSOC)保存数据,或者使用PDOStatement::execute()重新执行查询。