Python sqlite3.Row 怎样按列名读取查询结果
来源:17golang原创
时间:2026-11-02 11:55:37 197浏览 收藏
Python 的 sqlite3 查询默认返回元组,所以 row[0] 能取到第一列,但 row["name"] 会失败。要按列名读取,只需在创建游标之前把连接的 row_factory 设置为 sqlite3.Row;之后用 row["列名"]、row[索引] 或 row.keys() 访问即可。
官方文档:https://docs.python.org/3/library/sqlite3.html
核心写法是con = sqlite3.connect(":memory:")后执行con.row_factory = sqlite3.Row。这个设置只会影响之后从该连接创建的游标,已有游标不会自动切换。
默认元组为什么不适合按列名读取
查询结果的形状由连接或游标上的 row_factory 决定。默认值是 None,因此每一行是元组,列顺序完全由 SELECT 子句决定。元组适合位置固定、字段很少的场景,但当 SQL 增加列或调整投影顺序时,连续的数字下标容易变得不直观。
sqlite3.Row 是内置的行工厂,支持迭代、按索引访问和按列名映射访问。它不是普通字典,不能把所有字典方法都当作可用接口;需要列名清单时,使用它提供的 keys()。

先在连接上设置 sqlite3.Row
推荐把设置放在连接初始化阶段。这样从该连接后续创建的游标都会采用相同的行表示,业务函数不需要反复转换结果。
import sqlite3
# 连接级设置会传给之后创建的游标,适合统一约定查询结果形状。
con = sqlite3.connect(":memory:")
con.row_factory = sqlite3.Row
# 用别名让返回对象拥有稳定、可读的列名。
con.execute("CREATE TABLE user_profile (user_id INTEGER, display_name TEXT)")
con.execute(
"INSERT INTO user_profile (user_id, display_name) VALUES (?, ?)",
(7, "林默"),
)
# 查询返回 Row,而不是普通 tuple。
row = con.execute(
"SELECT user_id, display_name FROM user_profile WHERE user_id = ?",
(7,),
).fetchone()
if row is not None:
# 列名访问表达业务字段;索引访问仍然保留,便于兼容旧代码。
print(row["display_name"])
print(row[0])
# 连接不再使用时显式关闭,避免把资源生命周期交给垃圾回收。
con.close()
这里使用参数占位符传入用户编号,避免把外部输入拼进 SQL。fetchone() 找不到记录时返回 None,所以按列名读取前仍要先判断结果是否存在。
按列名读取时,列名来自 SELECT 结果
Row 的访问键不是 Python 变量名,而是查询结果中的列名。推荐在投影中明确写出字段,并在表达式或联表场景中使用 AS 起别名:
# 别名决定 Row 中的键,避免把表达式原文当作业务字段名。
row = con.execute(
"SELECT user_id AS id, display_name AS name "
"FROM user_profile WHERE user_id = ?",
(7,),
).fetchone()
if row is not None:
# keys() 返回当前查询结果的列名列表,可用于展示或调试。
print(row.keys())
print(row["id"], row["name"])
官方文档说明,列名访问不区分大小写,因此 row["name"] 与 row["NAME"] 可以指向同一列。但工程上仍建议统一 SQL 别名大小写,避免不同数据库或人工维护时产生阅读差异。
老游标为什么仍然返回元组
一个容易被忽略的迁移边界是设置时机。连接的 row_factory 是新游标的初始配置;如果游标已经创建,再修改连接属性,已有游标不会自动更新。
import sqlite3
con = sqlite3.connect(":memory:")
old_cursor = con.cursor()
# 这个设置不会回溯修改已经创建的 old_cursor。
con.row_factory = sqlite3.Row
new_cursor = con.cursor()
# 旧游标与新游标的行类型可能不同;迁移时应统一创建顺序。
old_cursor.execute("SELECT 1 AS value")
new_cursor.execute("SELECT 1 AS value")
old_row = old_cursor.fetchone()
new_row = new_cursor.fetchone()
print(type(old_row).__name__, type(new_row).__name__)
old_cursor.close()
new_cursor.close()
con.close()
如果项目封装了连接池或游标工厂,最稳妥的做法是在连接交给业务代码前就设置 row_factory,并避免在中途对同一连接混用两种结果形状。
重复列名和空结果要单独处理
Row 能按列名读取,但它不能替调用方解决重复列名。联表查询如果同时选择两个同名字段,访问某个重复键时应先给列起明确别名;否则读者看到的键与实际业务含义并不匹配。
# 联表时主动区分两个 id,避免 Row 的列名含义不清。
row = con.execute(
"SELECT u.user_id AS user_id, o.order_id AS order_id "
"FROM user_profile AS u JOIN orders AS o ON o.user_id = u.user_id "
"WHERE u.user_id = ?",
(7,),
).fetchone()
if row is None:
# 没有匹配行时不能直接写 row["order_id"]。
print("没有订单")
else:
print(row["user_id"], row["order_id"])
如果业务需要字典序列化,可以在边界处显式转换,例如用 {key: row[key] for key in row.keys()} 生成普通字典。不要为了方便把所有查询都改成自定义字典工厂:字典更适合需要 JSON 化的边界,Row 更适合保留轻量的按名、按索引读取能力。

迁移时可以按这张表快速判断
| 场景 | 建议 | 原因 |
|---|---|---|
| 字段位置长期固定 | 保留元组 | 下标简单且无额外命名约定 |
| 查询字段会调整 | 使用 sqlite3.Row | 按列名表达业务含义 |
| 联表有同名字段 | 用 AS 起别名 | 避免键名含义不清 |
| fetchone() 可能为空 | 先判断 None | 避免对空结果按键读取 |
| 需要输出 JSON | 边界处转 dict | 不要让内部结果形状扩散到所有层 |
最小核对顺序是:连接设置是否早于游标创建;SQL 是否给表达式和联表字段命名;读取前是否处理 None;循环读取时是否只使用当前查询返回的键。这样就能把“按列名读取”从一处技巧变成稳定的数据访问约定。
sqlite3.Row 能不能像字典一样调用 get?
不要把它当作完整字典使用。按列名读取用下标语法,列名清单用 keys();如果确实需要 get() 等字典行为,在边界处显式转换为字典。
可以只给一个游标设置 row_factory 吗?
可以,游标的 row_factory 也能单独设置。但连接级设置更容易保持多个游标的一致性;只影响单个查询时才考虑游标级覆盖。
列名访问大小写不敏感,还要统一别名吗?
要。大小写不敏感解决的是访问便利,不解决联表重复字段、表达式名称不稳定和团队阅读问题。统一别名仍然是更清晰的接口约定。
Python sqlite3.Row 的关键不是把查询结果“变成字典”,而是为同一行保留轻量的列名映射。把设置放在连接初始化阶段,用明确的 SQL 别名,并在读取前处理空结果,基本就能覆盖按列名读取时最常见的迁移问题。
-
457 收藏
-
266 收藏
-
455 收藏
-
243 收藏
-
378 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习