我有以下 PostgreSQL 数据库表:
TABLE session_monitor
(
id int,
customer_name varchar(150)
)
当我运行以下代码时:
seq = pg_cur.execute("SELECT id ,customer_name from session_monitor")
for id, customer_name in seq:
print(id)
print(customer_name)
它工作正常。
但是当我尝试
pg_cur.execute("SELECT max(id) as max_id from session_monitor")
for max_id in seq:
print(max_id)
我没有得到数字,而是:Row(max_id= 5)
我尝试了一种解决问题的方法:
seq = pg_cur.execute("SELECT max(id) as max_id,1 as one from session_monitor")
for max_id, one in seq:
print(max_id)
但这样使用它似乎有些蹩脚。
我在这里做错了什么 - 在第二种情况下是否有不同的方法来迭代查询结果?
最佳答案
之所以会得到这个结果,是因为 DB API 2 的工作方式(它从数据库中返回行的元组),再加上 Python 的怪癖,即当您想要指定一个包含一个元素的元组时,您需要添加一个逗号。它与 PyGreSQL 关系不大。
所以,当你第一次这样做时,你会在 seq
中得到一个(命名的)元组序列:
seq = cur.execute("SELECT id, customer_name FROM session_monitor")
然后当您执行以下操作时,您将遍历该序列同时解包您在每次迭代中获得的行元组到 id
和 customer_name
:
for id, customer_name in seq:
print(id)
print(customer_name)
当您只选择一列时,就像这样,您仍然得到一系列(命名的)元组,每个元组只有一个元素:
seq = cur.execute("SELECT max(id) AS max_id FROM session_monitor")
现在您尝试像这样迭代序列:
for max_id in seq:
print(max_id)
与上面的循环不同的是,这个循环不进行元组解包。所以 max_id
将是打印的完整行。
要像上面那样使用元组解包,您需要在 max_id
之后添加一个逗号:
for max_id, in seq:
print(max_id)
这将打印出您所期望的。顺便说一句,您还可以在元组解包表达式周围添加括号。但是,如果一个元组只有一个元素,您仍然需要一个逗号。
当然,如果你只有一行一列,你可以这样做:
seq = cur.execute("SELECT max(id) AS max_id FROM session_monitor")
max_id = list(seq)[0][0]
print(max_id)
或者,也可以使用 fetchone()
方法:
cur.execute("SELECT max(id) as max_id FROM session_monitor")
max_id = cur.fetchone()[0]
print(max_id)
当然,您也可以利用命名元组这一事实:
cur.execute("SELECT max(id) as max_id from session_monitor")
print(cur.fetchone().max_id)
作为旁注,使用“经典”PyGreSQL 接口(interface)而不是 DB API 2,您可以这样做:
q = db.query('SELECT max(id) FROM session_monitor')
print(q.singlescalar())
single()
方法获取单行,如 fetchone()
,singlescalar()
获取该行的第一列。
关于python - PyGreSQL 为一列选择语句返回意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62025882/