web-dev-qa-db-ja.com

psycopg2でパラメーターのリストをSQLに渡す

データベースからフェッチする行のIDのリストがあります。 pythonとpsycopg2を使用していますが、私の問題はこれらのIDを効果的にSQLに渡す方法ですか?)つまり、そのリストの長さがわかっていれば、いつでも簡単に手動または自動で「%s」式を必要なだけクエリ文字列に追加しますが、ここではどれだけ必要なのかわかりません。sql "id IN(id1、id2 、...) "ステートメント。リストの長さをチェックし、適切な数の"%s "をクエリ文字列に連結できることは知っていますが、非常に遅くて見苦しいでしょう。それを解決する方法についてのアイデアがありますか?そして、なぜ「IN」ステートメントでそれを行う必要があるのか​​尋ねないでください-これは、クラスの割り当ての一部であるベンチマークです。

44
k_wisniewski

Pythonタプルはpsycopg2でSQLリストに変換されます。

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

出力します

'SELECT * FROM table WHERE column IN (1,2,3);'

Python newcomersの場合:残念ながら、ここではリストではなくタプルを使用することが重要です。2つ目の例を次に示します。

cur.mogrify("SELECT * FROM table WHERE column IN %s;", 
    Tuple([row[0] for row in rows]))
71

この質問は古く、新しい質問があるかもしれませんが、私の同僚が今行っている答えは次のとおりです。

sql = "SELECT * FROM table WHERE column = ANY(%(parameter_array)s)"
cur.execute(sql,{"parameter_array": [1, 2, 3]})
2
Brandon Henry

これで、psycopg2のsqlモジュール( https://www.psycopg.org/docs/sql.html )を使用して、エラーや注入を防ぐことができます。例:

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

注意: sql.Identifierは、必要に応じて引用符を追加するため、PostgreSQLで引用符で囲まれた識別子を使用する場合にも機能します(大文字と小文字を区別する命名を可能にするために使用する必要があります)。

Database.iniの例と構造:

[postgresql]
Host=localhost
port=5432
database=postgres
user=user
password=mypass
2