Как безопасно параметризовать идентификаторы pyodbc в запросах?

Я написал небольшой инструмент, который переносит данные с SQL Server на Postgres.

Чтобы все заработало, я сделал это быстро и грязно, используя конкатенацию строк, поскольку мне нужно было решить множество других проблем, и в то время я не хотел возиться с SQL. Но теперь, когда все разобралось, я хочу делать все правильно в отделе SQL.

Небезопасная быстрая и грязная версия:

import pyodbc
# this is the bad example DON'T do this
    def getDataFromTable(self,table):
        """
        Gets all data from the specified Table.
        table -- Table name as string
        """
        cursor = self.cursor
        SQL = f"""SELECT * FROM {table}""" ## DON'T do this
        cursor.execute(SQL)
        rows = cursor.fetchall()
        records = []
        for row in rows:
            records.append(list(row))
        return records

Это работает отлично, но ожидает SQL-инъекция.

Я хочу построить что-то вроде этого (я пропустил неизменные части):

...
cursor = self.cursor
SQL = f"""SELECT * FROM ?""" # Use parameters insted of string concats
cursor.execute(SQL, table) # pass parameters to the execute method.
rows = cursor.fetchall()
...

Сейф выглядит неплохо, но тоже не работает. Выскакивает следующая ошибка:

pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft] [Драйвер ODBC SQL Server] [SQL Server] Die @ P1-Tabellenvariable muss deklariert werden. (1087) (SQLExecDirectW); [42000] [Microsoft] [ODBC Драйвер SQL Server] [SQL Server] Anweisung (en) konnte (n) nicht vorbereitet werden. (8180) ')

Это на немецком языке, но примерно переводится как: переменные таблицы должны быть объявлены, оператор не может быть подготовлен.

Как я могу передать переменную в метод execute, чтобы безопасно разместить идентификаторы?


person jdoe    schedule 18.02.2020    source источник


Ответы (1)


У вас не может быть переменной для имени таблицы в SQL Server. Вы можете сгенерировать строку на Python, а затем выполнить ее.

table_name = 'table1' 
query = "Select * from %s" % table_name

Или вы можете использовать динамический SQL.

person Naveen Kumar    schedule 18.02.2020
comment
Привет, спасибо, я пробовал это, но это тоже не работает, хотя ошибка изменилась: pyodbc.ProgrammingError: ('SQL содержит 0 маркеров параметров, но был предоставлен 1 параметр', 'HY000') - person jdoe; 18.02.2020