带有MySQL UPDATE的Python cursor.execute()导致语法错误

时间:2019-01-03 01:06:04

标签: python mysql sql-injection

下面以this示例为例,我试图重写与可防止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 :(得分:1)

根据文档编制的最佳方法是:

from psycopg2 import sql

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

Source

答案 1 :(得分:0)

您的SQL在所有3个示例中都不正确。 以下代码应该起作用:

let counter = 0;
const f = (intervalID) => {
    console.log("Hello World");
    counter += 1
    console.log(intervalID)
    if (counter ==5){
        console.log("Done")
        clearInterval(intervalID)
    }

}

const intervalID = setInterval(() => f(intervalID), 1000)

请注意表名和列名前后的反引号(`),但是,值应表示为列各自的对象类型。应该使用单引号和双引号来表示字符串值。

在您的情况下,FALSE最有可能不应该存储为字符串,而是存储在数据库模式中的布尔值或tinyint。

答案 2 :(得分:0)

在像这样的实例中,我试图使用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)

答案 3 :(得分:0)

感谢您的提示。最终,我在阅读了此post之后发现了自己的错误。显然,您无法参数化表名!

这是我固定代码的方式:

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

sql_update = "UPDATE " + table + " SET " + column + " = %s"
cursor.execute(sql_update, (value,))

答案 4 :(得分:0)

由于您的问题是有关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)。