[英]python-mysql cursor.execute failing with access denied error
[英]Python cursor.execute() with MySQL UPDATE causes syntax error
按照这个例子,我试图重写代码,以防止 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
我不确定我做错了什么,所以任何指针都将不胜感激。
根据文档执行此操作的最佳方法是:
from psycopg2 import sql
cur.execute(
sql.SQL("insert into {} values (%s, %s)")
.format(sql.Identifier('my_table')),
[10, 20])
您的 SQL 在所有 3 个示例中都不正确。 以下代码应该可以工作:
table = "led_status"
field = "test_led"
value = False
cursor.execute("UPDATE `%s` SET `%s` = %s", (table, field, value))
请注意表名和列名周围的反引号 (`),但是,值应表示为列各自的对象类型。 应使用单引号和双引号来表示字符串值。
在您的情况下, FALSE 很可能不应该存储为字符串,而是数据库架构中的布尔值或 tinyint 。
我喜欢在这样的情况下使用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)
谢谢你的提示。 最终我在阅读这篇文章后发现了我的错误。 显然你不能参数化一个表名!
这是我修复代码的方式:
table = "led_status"
field = "test_led"
value = "FALSE"
sql_update = "UPDATE " + table + " SET " + column + " = %s"
cursor.execute(sql_update, (value,))
由于您的问题是关于 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)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.