Python中的sqlite3:手动字符串格式是否可以安全地选择或更新变量列?

时间:2016-09-03 19:45:28

标签: python sqlite

众所周知,不应该使用本机字符串操作来组装SQL查询,而是使用带有占位符的预处理语句来表示变量。 Python中的sqlite3以这种方式处理:

c.execute('UPDATE stock SET price = ? WHERE symbol = ?', the_price, the_symbol)

此方法的限制是无法为选定或更新的列设置参数。在上面的示例中,价格列已更新。但是,其他请求将以相同的方式更新另一列。除了列的名称之外,这些请求中的每一个都几乎相同。因此,关于DRY(不要重复自己),做以下事情变得非常诱人:

if my_col in LIST_OK_COLUMNS:
    c.execute('UPDATE stock SET {} = ? WHERE symbol = ?'.format(my_col), the_symbol, the_price)

但是,这是一个使用本机字符串操作构建的查询,根据文档说这是不安全的。

正确执行此操作的最标准方法是什么?

1 个答案:

答案 0 :(得分:0)

如果您直接插入SQL语句的任何字符串可能被用户控制,则表示您遇到问题。

对于值,您可以使用SQL参数。

对于表/列名称没有这样的机制(因为通常不会要求用户提供这些名称; SQL是在恶意互联网之前设计的,其中一半的应用程序在不受信任的客户端上运行)。

要使price = -100 WHERE 1 OR symbol = ? --等列名无害,您必须正确转义它:

def sql_escape_identifier(s):
    return '"' + s.replace('"', '""') + '"'

c.execute('UPDATE stock SET {} = ...'.format(sql_escape_identifier(my_col)), ...