python cursor.execute()和mysql update导致语法错误

ppcbkaq5  于 2021-06-17  发布在  Mysql
关注(0)|答案(5)|浏览(646)

下面的示例中,我试图重写使用防止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

我不确定我做错了什么,所以任何指点都将不胜感激。

r1zhe5dt

r1zhe5dt1#

我喜欢用 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)
az31mfrm

az31mfrm2#

根据文档,最佳的方法是:

from psycopg2 import sql

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

来源

tvmytwxo

tvmytwxo3#

因为您的问题是关于sql注入的,所以我将比给出一行代码更进一步。您的问题是无法参数化表名。在处理sql注入时,必须区分动态sql和用户输入值之间的差异。防止sql注入的转义值应该由驱动程序的引号/转义机制来处理。您需要自己验证动态sql片段。动态sql片段包括variable where条件表达式、变量表名称或变量选择字段列表等内容。
您的示例的正确语法是:

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\u catalog)来动态获取这些表,但仍应检查特殊字段/表名(例如oid)。

41zrol4v

41zrol4v4#

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

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

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

注意表名和列名周围的倒钩(`),但是,值应该表示为相应对象类型的列。应使用单引号和双引号表示字符串值。
在您的例子中,false很可能不应存储为字符串,而是在数据库模式中存储为布尔值或tinyint。

lvjbypge

lvjbypge5#

谢谢你的小费。读了这篇文章后,我终于发现了我的错误。显然不能参数化表名!
我就是这样修改代码的:

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

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

相关问题