使用 psycopg2 执行许多 SELECT 查询

Posted

技术标签:

【中文标题】使用 psycopg2 执行许多 SELECT 查询【英文标题】:Executemany SELECT queries with psycopg2 【发布时间】:2018-10-24 09:17:12 【问题描述】:

我有一个使用psycopg2 连接的大量用户的postgresql 数据库。我需要检索 (SELECT) 特定大型用户子集 (>200) 的信息。我得到了一个 ID 列表,我需要返回每个用户的 age。我提出了一个可行的解决方案:

conn = psycopg2.connect("dbname= bla bla bla")
cur = conn.cursor()

for user_id in interesting_users:
    qr =  "SELECT age FROM users WHERE country_code = 0 AND user_id = 1".format(1, user_id)
    cur.execute(qr)
    fetched_row = cur.fetchall()
    #parse results

这个解决方案可以正常工作,但是当interesting_users 的长度很大时它并不理想。我正在寻找一种比执行多个查询更有效的方法。一种解决方案是通过附加所有用户 ID 创建单个查询:

for user_id in interesting_users:
    query += "OR user_id 0".format(user_id)

但我希望有一个更优雅的解决方案。

我发现psycopg2 提供了executemany() 方法。所以,我试图应用到我的问题。但是,我无法让它工作。这个:

cur.executemany("SELECT age FROM users WHERE country_code = %s AND user_id = %s",[(1, user_id) for user_id in interesting_users])
r = cur.fetchall() 

返回:

r = cur.fetchall()
psycopg2.ProgrammingError: no results to fetch

那么,executemany() 可以用于SELECT 语句吗?如果是,我的代码有什么问题?如果不是,如何一次执行多个SELECT 查询? 注意interesting_users 中的 id 没有顺序,所以我不能使用 WHERE id < ... 之类的东西

解决方案

query =  "SELECT age FROM users WHERE country_code = 0 AND user_id IN (1);".format(1, ",".join(map(str, interesting_users)))
cur.execute(query)
fetched_rows = cur.fetchall()

【问题讨论】:

永远不要将参数格式化为 SQL 语句,使用参数,就像在第二个示例中一样。 是否必须关闭或提交游标或连接? 【参考方案1】:

executemany 仅适用于 INSERT,不适用于 SELECT。使用IN

cur.executemany("SELECT age FROM users WHERE country_code = %s AND user_id IN ()".format(','.join(['%s'] * len(interesting_users)),
    [1] + interesting_users)
r = cur.fetchall() 

【讨论】:

感谢您的回答,但我得到TypeError: Required argument 'vars_list' (pos 2) not found 即使第一个参数是“'%s,%s,%s,%s'”,第二个参数是列表 [1, 1526081542 , 1526309772, 1526151777, 1526254283]。知道为什么吗? 检查你的括号,听起来好像括号放错了地方 我修复了括号错误,我必须将列表作为元组传递,否则我得到"TypeError: 'int' object does not support indexing"。但是,在使用cur.executemany("SELECT age FROM users WHERE country_code = %s AND user_id IN ()".format(','.join(['%s'] * len(interesting_users))), ([1] + interesting_users,)) 时,我仍然会得到psycopg2.ProgrammingError: no results to fetch"。知道为什么吗?

以上是关于使用 psycopg2 执行许多 SELECT 查询的主要内容,如果未能解决你的问题,请参考以下文章

psycopg2转义字符问题

如何显式引用字符串值(Python DB API/Psycopg2)

测试 PostgreSQL 表是不是不存在(使用 psycopg2)

psycopg2“选择更新”

psycopg2 选择 NULL 值

psycopg2 连接问题,无法选择列,但连接正常