Python sqlite3.Cursor.fetchall 方法
上次修改时间:2025 年 4 月 15 日
本综合指南探讨 Python 的 sqlite3.Cursor.fetchall
方法,这是从 SQLite 数据库检索所有查询结果的主要方式。我们将介绍基本用法、性能考虑因素和实际示例。
基本定义
fetchall
方法检索查询结果集中的所有剩余行。它返回一个元组列表,其中每个元组代表数据库中的一行。
主要特征:它一次性消耗所有结果,如果没有行可用则返回一个空列表,并且应该在执行带有游标的 SELECT 语句后使用。
fetchall 的基本用法
这是 fetchall
的最简单用法,用于检索表中的所有行。 该示例演示了使用上下文管理器的正确资源管理。
import sqlite3 # Using context managers for both connection and cursor with sqlite3.connect('example.db') as conn: with conn.cursor() as cursor: cursor.execute("SELECT * FROM users") all_rows = cursor.fetchall() for row in all_rows: print(f"ID: {row[0]}, Name: {row[1]}, Age: {row[2]}")
此示例显示了基本工作流程:连接到数据库,创建游标,执行 SELECT 查询,获取所有结果,并迭代它们。上下文管理器确保正确的资源清理。
fetchall
方法将所有行作为元组列表返回,其中每个元组包含 SELECT 语句中指定的顺序的列值。
获取空结果
当没有行与查询匹配时,fetchall
返回一个空列表,而不是 None 或引发异常。 此示例演示了此行为。
import sqlite3 with sqlite3.connect('example.db') as conn: with conn.cursor() as cursor: # Query with no matching rows cursor.execute("SELECT * FROM users WHERE age > 100") results = cursor.fetchall() print(f"Number of rows: {len(results)}") # 0 print(f"Type of results: {type(results)}") # <class 'list'>
此示例表明 fetchall
始终返回一个列表,即使未找到任何行。 此行为使其可以安全地迭代结果而无需额外的类型检查。
空列表返回值对于需要以相同方式处理填充和空结果集的条件逻辑非常有用。
与参数化查询结合使用
fetchall
可以与参数化查询无缝协作,这对于防止 SQL 注入至关重要。 此示例演示了这种组合。
import sqlite3 min_age = 25 max_age = 40 with sqlite3.connect('example.db') as conn: with conn.cursor() as cursor: # Parameterized query with fetchall cursor.execute( "SELECT * FROM users WHERE age BETWEEN ? AND ?", (min_age, max_age) ) matching_users = cursor.fetchall() for user in matching_users: print(user)
此示例演示了如何在查询中安全地使用参数,同时仍然可以从 fetchall
中受益以检索所有匹配的行。 参数作为元组传递给 execute 方法。
参数化查询对于安全性至关重要,并且还可以通过允许 SQLite 重用具有不同值的类似查询的查询计划来提高性能。
处理大型结果集
虽然 fetchall
很方便,但它会一次性将所有结果加载到内存中。 对于大型数据集,请考虑使用 fetchmany
等替代方法。
import sqlite3 with sqlite3.connect('large_db.db') as conn: with conn.cursor() as cursor: cursor.execute("SELECT * FROM big_table") # Process in batches to reduce memory usage batch_size = 1000 while True: batch = cursor.fetchmany(batch_size) if not batch: break for row in batch: process_row(row) # Your processing function
此示例演示了针对大型数据集的更节省内存的方法。 虽然它不使用 fetchall
,但了解何时不使用它非常重要。
对于中等大小的结果集(最多数千行),fetchall
是完全可以接受的,并且通常比手动批处理更方便。
与自定义行工厂一起使用
fetchall
可以与自定义行工厂很好地配合使用,这些工厂可以转换行的表示方式。 此示例使用内置的 sqlite3.Row
。
import sqlite3 with sqlite3.connect('example.db') as conn: conn.row_factory = sqlite3.Row # Enable named column access with conn.cursor() as cursor: cursor.execute("SELECT name, age FROM users") rows = cursor.fetchall() for row in rows: print(f"{row['name']} is {row['age']} years old")
此示例显示了当使用 sqlite3.Row
工厂时,fetchall
如何返回可以通过索引和列名访问的行。
Row
工厂在便利性和性能之间提供了很好的平衡,使代码更具可读性,同时保持效率。
与 JOIN 操作结合使用
fetchall
可以处理带有 JOIN 的复杂查询,并在一次调用中返回所有相关数据。 此示例演示了一个多表查询。
import sqlite3 with sqlite3.connect('library.db') as conn: with conn.cursor() as cursor: query = """ SELECT books.title, authors.name, books.publication_year FROM books JOIN authors ON books.author_id = authors.id WHERE books.genre = ? """ cursor.execute(query, ('Science Fiction',)) sci_fi_books = cursor.fetchall() for book in sci_fi_books: title, author, year = book print(f"{title} by {author} ({year})")
此示例显示了 fetchall
与 JOIN 查询一起使用,该查询组合了来自多个表的数据。 每个返回的元组都包含来自 JOIN 中所有表的列。
该方法可以像简单单表查询一样很好地处理复杂的结果集,使其适用于各种查询类型。
与聚合函数一起使用
fetchall
可用于使用 COUNT、SUM 或 AVG 等聚合函数的查询。 此示例演示了统计查询。
import sqlite3 with sqlite3.connect('sales.db') as conn: with conn.cursor() as cursor: # Multiple aggregate functions in one query cursor.execute(""" SELECT COUNT(*) as total_orders, AVG(amount) as avg_amount, MAX(amount) as max_sale, MIN(amount) as min_sale FROM orders WHERE order_date BETWEEN ? AND ? """, ('2024-01-01', '2024-12-31')) stats = cursor.fetchall()[0] # Get first (and only) row print(f"Total orders: {stats[0]}") print(f"Average amount: ${stats[1]:.2f}") print(f"Largest sale: ${stats[2]:.2f}") print(f"Smallest sale: ${stats[3]:.2f}")
此示例显示了 fetchall
如何与返回单行计算值的聚合查询一起使用。 我们从结果列表中访问第一行(也是唯一一行)。
即使对于单行结果,fetchall
也会返回包含一个元组的列表,从而在所有查询类型中保持一致的行为。
最佳实践
- 用于中等结果集: 避免用于非常大的数据集
- 正确关闭资源: 始终使用上下文管理器
- 与参数化查询结合使用: 为了安全起见
- 考虑内存使用情况: 注意数据集大小
- 使用行工厂: 为了更具可读性的代码
资料来源
作者
列出所有 Python 教程。