在使用 Python 进行数据库查询,通常情况下 cursor
的 fetchall
, fetchmany
返回的是元组(Tuple) 的列表,所以对查询到的结果只能用索引下标来访问,而无法通过字段名来获取值。对 Java JDBC 的 ResultSet 操作,我们有两种获取值的方式,resultSet.getString(1) 和 resultSet.getString('name')。
其实只要能用数字索引访问到字段值也就足够了,查询后字段名可以由 cursor.description
获得。通过字段名来访问值唯一的好处估计是出错的概率小些罢了,比如 result['firstname'], result['lastname'] 总是比 result[1], result[2] 更不容易搞混,错误定位也会更轻松。
假如有下面的数据库表与两条记录
create table test(name varchar(10), count integer);
insert into test(name, count) values ('Bob', 1), ('Joe', 8);
以 SQLite 数据库操作代码为例
打印出来的结果是
[('Bob', 1), ('Joe', 8)]
对结果进行遍历的方式可以是以下几种方式
或
或
如果希望查询得到的结果集是一个带有字段名与值的字典的话,也就是说可能像 JDBC resultSet 那样通过字段名来访问值该如何定制呢?对于不同的数据库实现方式略有不同
通用方式(适用于所有数据库)
首先,前面提到的,查询后的字段名称可由 cursor.description
获得,下面的代码会打印出每个字段的名称
如果把字段时的列表与每一行结果的 Tuple 以 zip相结合就能得到一个字典行
上面输出的结果是
{'name': 'Bob', 'count': 1}
{'name': 'Joe', 'count': 8}
SQLite 结果集返回字典
SQLite 就是基于这一通用的方式来设定连接的 row_factory
函数属性的,完整代码如下:
cursor.fetchall()
获得的结果输出为
[{'name': 'Bob', 'count': 1}, {'name': 'Joe', 'count': 8}]
它是一个字典列表,访问方式就要用字典的方式,如
MySQL 返回字典结果集
设置 conn.row_factory
的方式对 MySQL 是不奏效了。幸好 MySQLdb 库预备好了不同的打开 cursor 的方式
此时 cursor.fetchall()
的结果也是
({'name': 'Bob', 'count': 1}, {'name': 'Joe', 'count': 8})
如果没有设置 cursor
类型为 MySQLdb.cursors.DictCursor
, 得到的结果也是 [('Bob', 1), ('Joe', 8)]
。
注:关于 MySQLdb
的安装方法,可参考 https://pypi.org/project/mysqlclient/,在 Ubuntu 平台下是
$ sudo apt-get install default-libmysqlclient-dev
$ pip3 install mysqlclient
MySQL 还有一个 Python 驱动,可用 pip3 install mysql-connector
安装,尚不知道如何返回字典结果集
另外,PostgreSQL 也能用类似的方式
SQL Server 返回字典结果集
用 SQL Server 的驱动 pymssql
让结果集返回为字典的方式就更为直截了当,只需要设置 cursor 的 as_dict
属性为 True
就行了。详见下方代码
打印的结果为
[{'name': 'Bob', 'count': 1}, {'name': 'Joe', 'count': 8}]
上面基本涵盖了我们常用的数据库类型,MySQL, PostgreSQL 和 SQL Server。Python 默认查询只是返回一个不含有字段名的结果集(List of Tuple),这个需求基本上就满足了。可能很少情况下真正需要 Python 查询数据库后返回一个字典结果集,如果真有如此需求的话,以上内容可供参考。
补充(2021-09-17): PostgreSQL 中的做法
链接:
优秀
[…] 假如有下面的数据库表与两条记录 阅读全文 >> […]