Python cursor.execute () с MySQL UPDATE вызывает синтаксическую ошибку - PullRequest
0 голосов
/ 03 января 2019

Следуя этому примеру, я пытаюсь переписать код, который работает с кодом, защищающим от внедрения SQL:

Код, который работает:

table = "led_status"
field = "test_led"
value = "FALSE"

cursor.execute(("UPDATE %s SET %s = %s") % (table, field, value))

код, который делаетне работает:

table = "led_status"
field = "test_led"
value = "FALSE"

cursor.execute(("UPDATE %s SET %s = %s", table, field, value))

Этот код также не работает:

table = "led_status"
field = "test_led"
value = "FALSE"

sql_update_command = "UPDATE %s SET %s = %s"
cursor.execute(sql_update_command, (table, field, value))

Первый пример работает, другие не работают, и каждый из них выдает синтаксическую ошибку:

mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''led_status' SET 'test_led' = 'FALSE'' at line 1

Я не уверен, что я делаю неправильно, поэтому любые указатели будут с благодарностью.

Ответы [ 5 ]

0 голосов
/ 04 января 2019

Поскольку ваш вопрос касается внедрения SQL, я пойду немного дальше, чем дать вам один вкладыш.Ваша проблема в том, что вы не можете параметризовать имя таблицы.При работе с SQL-инъекцией вы должны различать динамический SQL-запрос и вводимые пользователем значения.Экранирование значений для защиты от внедрения SQL должно обрабатываться механизмом кавычек / экранирования драйвера.Вы самостоятельно проверяете фрагменты динамического SQL.К фрагментам динамического SQL относятся такие вещи, как выражения условий переменной WHERE, имена таблиц переменных или списки полей переменных SELECT.

Правильный синтаксис для вашего примера:

cursor.execute("UPDATE {} SET {} = %s".format(table, field), value)

или

cursor.execute("UPDATE %s SET %s = %%s" % (table, field), value)

Однако, если таблица получена от пользователя, вы должны проверить ее по некоторому предопределенному списку, прежде чем перейти к этому утверждению.Вы не можете доверять базе данных, чтобы делать правильные вещи с именами таблиц или полей.Следующая структура данных предоставит что-то для проверки, например:

valid_fields = {
   'table_1': ['field_1', 'field_2'],
   'table_2': ['field_a', 'field_b'],
   'table_3': ['field_x', 'field_y']
}

Вы также можете использовать специальные таблицы каталога, которые предоставляет ваша база данных (например, pg_catalog), чтобы получить их динамически, но вы все равно должны проверить наличие специального поля/ имена таблиц (например, OID).

0 голосов
/ 04 января 2019

Оптимальный способ сделать это в соответствии с документацией:

from psycopg2 import sql

cur.execute(
sql.SQL("insert into {} values (%s, %s)")
    .format(sql.Identifier('my_table')),
[10, 20])

Источник

0 голосов
/ 03 января 2019

Мне нравится использовать psycopg2 для подобных случаев, когда вы пытаетесь указать имя столбца в качестве ввода и не хотите, чтобы оно экранировалось

from psycopg2.extensions import AsIs

cmd = """
      UPDATE %(table)s SET %(column)s = %(val)s
      """

kwargs = {
    'table': AsIs('led_status'),
    'column': AsIs('test_led'),
    'val': False
}

cursor.execute(cmd, kwargs)
0 голосов
/ 03 января 2019

Спасибо за советы.В конце концов я понял свою ошибку после прочтения этой записи .Очевидно, вы не можете параметризовать имя таблицы!

Вот как я исправил код:

table = "led_status"
field = "test_led"
value = "FALSE"

sql_update = "UPDATE " + table + " SET " + column + " = %s"
cursor.execute(sql_update, (value,))
0 голосов
/ 03 января 2019

Ваш SQL неверен во всех 3 примерах. Следующий код должен работать:

table = "led_status"
field = "test_led"
value = False

cursor.execute("UPDATE %s SET `%s` = %s", (table, field, value))

Обратите внимание на обратные пометки (`) вокруг имен таблиц и столбцов, однако значения должны быть представлены в виде столбцов соответствующего типа объекта. Одинарные и двойные кавычки должны использоваться для представления строковых значений.

В вашем случае FALSE, скорее всего, следует хранить не в виде строки, а в виде логического значения или tinyint в схеме базы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...