psycopg2 cursor.execute() с параметром запроса SQL вызывает синтаксическую ошибку
При указании параметра для execute() в psycopg2 в Python, вот так:
cursor.execute('SELECT * FROM %s', ("my_table", ))
Я получаю эту ошибку:
psycopg2.ProgrammingError: syntax error at or near "'my_table'"
LINE 1: SELECT * FROM 'my_table'
Что я делаю неправильно? Похоже, что psycopg2 добавляет одинарные кавычки в запрос, и эти одинарные кавычки вызывают синтаксическую ошибку.
Если я не использую параметр, он работает правильно:
cursor.execute('SELECT * FROM my_table')
3 ответа
Я считаю, что параметризованные операторы, подобные этому, предназначены для использования со значениями, а не с именами таблиц (или ключевыми словами SQL и т. Д.). Так что вам в основном не повезло с этим.
Тем не менее, не беспокойтесь, так как этот механизм предназначен для предотвращения внедрения SQL-кода, и вы обычно знаете, к какой таблице вы хотите получить доступ во время написания кода, поэтому маловероятно, что кто-то может внедрить вредоносный код. Просто идите вперед и напишите таблицу в строке.
Если по какой-либо (возможно, извращенной) причине вы оставляете имя таблицы параметрическим:
- Если имя таблицы происходит из вашей программы (например, словарь или атрибут класса), тогда выполните обычную подстановку строк.
- Если имя таблицы происходит из внешнего мира (подумайте "пользовательский ввод"): либо не делайте этого, либо полностью доверяйте пользователю и применяйте предыдущий подход 1.
Например:
cursor.execute(
'SELECT * FROM %s where %s = %s'
% ("my_table", "colum_name", "%s"), #1
("'some;perverse'string;--drop table foobar")) #2
#1
: Пусть третий%s будет заменен другим '%s' в это время, чтобы разрешить последующую обработку psycopg2#2
: Это строка, которая будет правильно цитироваться psycopg2 и помещена вместо третьего "%s" в исходной строке.
В Psycopg2 есть функциональные возможности, которые поддерживают этот вариант использования через композицию строк SQL . Этот подход позволяет «динамически генерировать SQL удобным и безопасным способом».
В случае использования в исходном ответе:
cursor.execute(
sql.SQL("SELECT * FROM {}").format(
sql.Identifier("my_table")))
Использование композиции строк SQL является гораздо более безопасным подходом, чем интерполяция строковых параметров через
Предупреждение Никогда, никогда, НИКОГДА не используйте конкатенацию строк Python (+) или интерполяцию строковых параметров (%) для передачи переменных в строку запроса SQL. Даже не под прицелом.
cur.execute(
"""
SELECT * FROM %s;
""",
{"my_table",}
)
conn.commit()