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. Если имя таблицы происходит из вашей программы (например, словарь или атрибут класса), тогда выполните обычную подстановку строк.
  2. Если имя таблицы происходит из внешнего мира (подумайте "пользовательский ввод"): либо не делайте этого, либо полностью доверяйте пользователю и применяйте предыдущий подход 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 является гораздо более безопасным подходом, чем интерполяция строковых параметров через обсуждалось в ответе Ирфи. Как отмечено в документации psycopg2 :

Предупреждение Никогда, никогда, НИКОГДА не используйте конкатенацию строк Python (+) или интерполяцию строковых параметров (%) для передачи переменных в строку запроса SQL. Даже не под прицелом.

      cur.execute(
    """
    SELECT * FROM %s;
    """,
    {"my_table",}
)
conn.commit()
Другие вопросы по тегам