在psycopg2中将参数列表传递给SQL

k_w*_*ski 41 python postgresql psycopg2

我有一个从数据库中获取的行ID列表.我正在使用python和psycopg2,我的问题是如何有效地将这些ID传递给SQL?我的意思是,如果我知道该列表的长度,这很容易,因为我总是可以根据需要手动或自动将多少"%s"表达式添加到查询字符串中,但在这里我不知道我需要多少它们.重要的是我需要使用sql"id IN(id1,id2,...)"语句选择行.我知道可以检查列表的长度并将合适数量的"%s"连接到查询字符串中,但我担心它会非常缓慢和丑陋.有没有人知道如何解决它?请不要问为什么我需要用"IN"语句来做 - 这是一个基准测试,是我课堂作业的一部分.提前致谢!

phi*_*est 69

Python元组在psycopg2中转换为sql列表:

cur.mogrify("SELECT * FROM table WHERE column IN %s;", ((1,2,3),))
Run Code Online (Sandbox Code Playgroud)

会输出

'SELECT * FROM table WHERE column IN (1,2,3);'
Run Code Online (Sandbox Code Playgroud)

对于Python新手:不幸的是,使用元组非常重要,而不是列表.这是第二个例子:

cur.mogrify("SELECT * FROM table WHERE column IN %s;", 
    tuple([row[0] for row in rows]))
Run Code Online (Sandbox Code Playgroud)

  • 请注意,Python LISTS将转换为Postgres ARRAY类型,因此我发现我经常需要在cursor.execute(...)参数中执行类似(元组(SOME_LIST))的操作.注意我们如何将列表的元组()包装在单个元素文字元组中,因此我们有一个元组元组,如本例所示. (28认同)

Bra*_*nry 8

这个问题很老了,也许还有一个更新的问题,但我的同事们现在的答案是这样的:

sql = "SELECT * FROM table WHERE column = ANY(%(parameter_array)s)"
cur.execute(sql,{"parameter_array": [1, 2, 3]})
Run Code Online (Sandbox Code Playgroud)


Ale*_*nov 6

现在 psycopg2 ( https://www.psycopg.org/docs/sql.html ) 的sql 模块可用于防止错误和注入,例如:

import psycopg2
from psycopg2 import sql

params = config()
conn = psycopg2.connect(**params)
cur = conn.cursor()

ids = ['a','b','c']
sql_query = sql.SQL('SELECT * FROM {} WHERE id IN ({});').format(
                    sql.Identifier('table_name'),
                    sql.SQL(',').join(map(sql.Identifier, ids))
                )
print (sql_query.as_string(cur)) # for debug
cur.execute(sql_query)

from configparser import ConfigParser
def config(filename='database.ini', section='postgresql'):
    # create a parser
    parser = ConfigParser()
    # read config file
    parser.read(filename)

    # get section, default to postgresql
    db = {}
    if parser.has_section(section):
        params = parser.items(section)
        for param in params:
            db[param[0]] = param[1]
    else:
        raise Exception('Section {0} not found in the {1} file'.format(section, filename))

    return db
Run Code Online (Sandbox Code Playgroud)

注意:sql.Identifier如果需要,将添加引号,因此如果您在 PostgreSQL 中也使用带引号的标识符,它将起作用(它们必须用于允许例如区分大小写的命名)。

database.ini 的示例和结构:

[postgresql]
host=localhost
port=5432
database=postgres
user=user
password=mypass
Run Code Online (Sandbox Code Playgroud)