fetchall() 方法执行后,返回一个包含所有查询结果的列表。

这个列表中的每一个元素,都是一个元组,对应数据库中的一行数据,元组中的每个值,则对应该行中的一个字段(列)。
详细解释
基本工作原理
当你使用 Python 的数据库接口(如 sqlite3, psycopg2 for PostgreSQL, mysql-connector-python for MySQL 等)执行一个 SELECT 查询后,数据库服务器会返回一个结果集,这个结果集包含了所有匹配的行。
fetchall() 的作用就是一次性从结果集中获取所有的行,并将它们转换成 Python 的数据结构(列表的列表)。
返回值的具体形式
假设我们有下面一张 users 表:

| id | name | age | |
|---|---|---|---|
| 1 | Alice | alice@example.com | 30 |
| 2 | Bob | bob@example.com | 25 |
| 3 | Carol | carol@example.com | 35 |
当你执行 SELECT id, name, email FROM users; 后,fetchall() 的返回值会是这样的:
[
(1, 'Alice', 'alice@example.com'),
(2, 'Bob', 'bob@example.com'),
(3, 'Carol', 'carol@example.com')
]
- 最外层:是一个
list(列表)。 - 内层:列表中的每一个元素都是一个
tuple(元组)。 - 元组内:每个元组代表数据库中的一行数据,元组的顺序和数量与
SELECT语句中指定的列的顺序和数量完全一致。
代码示例 (使用 sqlite3)
这是一个完整的、可运行的例子,可以帮助你更好地理解。
import sqlite3
# 1. 连接到数据库 (如果不存在,则会创建)
# 使用 'with' 语句可以确保连接在完成后自动关闭
try:
with sqlite3.connect('example.db') as conn:
# 2. 创建一个游标对象
cursor = conn.cursor()
# 3. 创建一个表 (如果表已存在,则忽略)
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
age INTEGER
)
''')
# 4. 插入一些示例数据
# 使用 executemany 来插入多行数据
users_to_insert = [
('Alice', 'alice@example.com', 30),
('Bob', 'bob@example.com', 25),
('Carol', 'carol@example.com', 35)
]
cursor.executemany("INSERT INTO users (name, email, age) VALUES (?, ?, ?)", users_to_insert)
conn.commit() # 提交事务
# 5. 执行查询
print("--- 执行查询: SELECT name, age FROM users ---")
cursor.execute("SELECT name, age FROM users")
# 6. 使用 fetchall() 获取所有结果
all_results = cursor.fetchall()
# 7. 打印返回值
print("\nfetchall() 的返回值:")
print(all_results)
print("\n返回值的类型:", type(all_results))
# 8. 遍历结果
print("\n--- 遍历结果 ---")
for row in all_results:
# row 是一个元组
print(f"用户名: {row[0]}, 年龄: {row[1]}")
# 9. 查询所有列
print("\n--- 执行查询: SELECT * FROM users ---")
cursor.execute("SELECT * FROM users")
all_columns_results = cursor.fetchall()
print("\nfetchall() 的返回值 (所有列):")
print(all_columns_results)
except sqlite3.Error as e:
print(f"数据库错误: {e}")
运行上述代码的输出:
--- 执行查询: SELECT name, age FROM users ---
fetchall() 的返回值:
[('Alice', 30), ('Bob', 25), ('Carol', 35)]
返回值的类型: <class 'list'>
--- 遍历结果 ---
用户名: Alice, 年龄: 30
用户名: Bob, 年龄: 25
用户名: Carol, 年龄: 35
--- 执行查询: SELECT * FROM users ---
fetchall() 的返回值 (所有列):
[(1, 'Alice', 'alice@example.com', 30), (2, 'Bob', 'bob@example.com', 25), (3, 'Carol', 'carol@example.com', 35)]
fetchall() 的重要注意事项
结果集为空的情况
SELECT 查询没有匹配到任何数据,fetchall() 不会返回 None,而是返回一个空列表 []。
cursor.execute("SELECT name FROM users WHERE age = 100;")
no_results = cursor.fetchall()
print(no_results) # 输出: []
print(type(no_results)) # 输出: <class 'list'>
内存消耗 (大结果集的陷阱)
fetchall() 会将所有数据一次性加载到内存中,如果你的查询结果非常大(有几百万行数据),这可能会导致你的程序消耗大量内存,甚至导致程序崩溃。
对于大结果集,推荐使用 fetchone() 在一个循环中逐行获取数据:
# 推荐:处理大结果集的方法
cursor.execute("SELECT * FROM very_large_table")
while True:
row = cursor.fetchone()
if row is None:
break # 没有更多数据了
# 处理单行数据
print(row)
结果集的“一次性”特性
一个数据库游标的结果集通常只能被遍历一次,一旦你调用了 fetchall(),结果集中的数据就被“消耗”掉了,如果你再次调用 cursor.fetchall(),它会返回一个空列表 []。
cursor.execute("SELECT name, age FROM users")
first_fetch = cursor.fetchall()
print("第一次 fetchall():", first_fetch) # [('Alice', 30), ('Bob', 25), ('Carol', 35)]
second_fetch = cursor.fetchall()
print("第二次 fetchall():", second_fetch) # []
如果需要多次访问结果,你需要重新执行查询。
与其他 fetch 方法的比较
| 方法 | 描述 | 返回值 | 适用场景 |
|---|---|---|---|
fetchall() |
获取结果集中的所有剩余行。 | 一个包含所有行的列表。 | 结果集较小,且需要一次性处理所有数据。 |
fetchone() |
获取结果集中的下一行。 | 单个行(一个元组),如果无更多数据,则返回 None。 |
处理大结果集,或只需要一行数据时。 |
fetchmany(size) |
获取结果集中的指定数量的下一行。 | 一个包含 size 行的列表,如果剩余行不足 size,则返回剩余所有行。 |
分批处理大量数据,平衡内存使用和处理效率。 |
fetchall()返回一个列表,列表里是多个元组。- 每个元组代表一行数据。
- 元组中的元素顺序和数量与
SELECT语句中的列一致。 - 查询无结果时返回空列表
[]。 - 注意内存消耗,对大结果集使用
fetchone()或fetchmany()。
