web-dev-qa-db-ja.com

psycopg2 / Python DB-APIおよびPostgreSQLを使用したパラメーター化されたクエリ

Psycopg2にパラメータ化されたクエリをPostgreSQLに渡す最良の方法は何ですか?独自のエスケープメカニズムやアダプターを記述したくありません。psycopg2のソースコードと例は、Webブラウザーで読むのが難しいです。

PyGreSQLや別のpython pgアダプタなど)に切り替える必要がある場合、それで十分です。単純なパラメータ化が必要です。

43
jeffcook2150

psycopg2は、DB-API 2.0のルールに従います( PEP-249 で設定)。つまり、executeオブジェクトからcursorメソッドを呼び出してpyformatバインディングスタイルを使用すると、エスケープが行われます。たとえば、次のshouldは安全です(そして機能します)。

cursor.execute("SELECT * FROM student WHERE last_name = %(lname)s", 
               {"lname": "Robert'); DROP TABLE students;--"})
82
Hank Gay

Psycopgのドキュメントから

http://initd.org/psycopg/docs/usage.html

警告決して、決して、決してPython文字列連結(+)または文字列パラメータ補間(%)を使用して、SQLクエリ文字列に変数を渡さないでください。

SQLコマンドで変数を渡す正しい方法は、execute()メソッドの2番目の引数を使用することです。

SQL = "INSERT INTO authors (name) VALUES (%s);" # Note: no quotes

data = ("O'Reilly", )

cur.execute(SQL, data) # Note: no % operator

22
Fábio Dias

役立つと思われる例をいくつか示します

cursor.execute('SELECT * from table where id = %(some_id)d', {'some_id': 1234})

または、フィールド名、値のdictに基づいてクエリを動的に構築できます。

fields = ', '.join(my_dict.keys())
values = ', '.join(['%%(%s)s' % x for x in my_dict])
query = 'INSERT INTO some_table (%s) VALUES (%s)' % (fields, values)
cursor.execute(query, my_dict)

注:フィールドはコードで定義する必要がありますnotユーザー入力。そうしないと、SQLインジェクションの影響を受けやすくなります。

8
adam