3

我有以下 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)

但是像这样使用它似乎有点蹩脚。

我在这里做错了什么 - 在第二种情况下是否有不同的方法来迭代查询结果?

4

1 回答 1

2

由于 DB API 2 的工作方式(它从数据库中返回行的元组),再加上 Python 的怪癖,当您想用一个元素指定一个元组时,您需要添加一个逗号,您会得到这个结果。它与 PyGreSQL 关系不大。

所以,当你第一次这样做时,你会得到一个(命名的)元组序列seq

seq = cur.execute("SELECT id, customer_name FROM session_monitor")

然后,当您执行以下操作时,您将迭代该序列,同时将您在每次迭代中获得的行元组解包id到and 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)

与上面循环的不同之处在于,这个循环没有 tuple unpackingmax_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 接口而不是 DB API 2,您可以这样做:

q = db.query('SELECT max(id) FROM session_monitor')
print(q.singlescalar())

single()方法获取单行,如fetchone(),并singlescalar()获取该行的第一列。

于 2020-05-26T17:37:38.783 回答