Параметрированные запросы с помощью psycopg2/Python DB-API и PostgreSQL
Какой лучший способ заставить psycopg2 передать параметризованные запросы PostgreSQL? Я не хочу писать свои собственные механизмы escpaing или адаптеры, а исходный код psycopg2 и примеры трудно читать в веб-браузере.
Если мне нужно переключиться на что-то вроде PyGreSQL или другого pg-адаптера python, это прекрасно со мной. Мне просто нужна простая параметризация.
Ответы
Ответ 1
psycopg2
следует правилам для DB-API 2.0 (см. PEP-249). Это означает, что вы можете вызвать метод execute
из вашего объекта cursor
и использовать стиль привязки pyformat
, и он выполнит экранирование для вас. Например, следующее должно быть безопасным (и работать):
cursor.execute("SELECT * FROM student WHERE last_name = %(lname)s",
{"lname": "Robert'); DROP TABLE students;--"})
Ответ 2
Из документации psycopg
(http://initd.org/psycopg/docs/usage.html)
Предупреждение Никогда, никогда, НИКОГДА не используйте конкатенацию строк Python (+) или интерполяцию строковых параметров (%) для передачи переменных в строку запроса SQL. Даже под прицелом.
Правильный способ передачи переменных в команде SQL использует второй аргумент метода execute():
SQL = "INSERT INTO authors (name) VALUES (%s);" # Note: no quotes
data = ("O'Reilly", )
cur.execute(SQL, data) # Note: no % operator
Ответ 3
Вот несколько примеров, которые могут оказаться полезными
cursor.execute('SELECT * from table where id = %(some_id)d', {'some_id': 1234})
Или вы можете динамически строить свой запрос на основе имени имени поля, значение:
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)
Примечание: поля должны быть определены в вашем коде, не, но вы будете восприимчивы к SQL-инъекции.