在Python中使用MySQLdb执行这样的SQL查询安全吗?

4 投票
2 回答
1394 浏览
提问于 2025-04-17 12:32

我注意到大多数资料都说,在Python中执行SQL语句的最佳做法是这样的:

cursor.execute( 'select * from coworkers where name = :1 and clue > :2', [ name, clue_threshold ] )

其他资料则说

cursor.execute( "select * from coworkers where name = %s and clue > %s", ( name, clue_threshold ) )

我觉得这两者挺相似的。

无论如何,我一直在做的是创建一个字典来存储值。例如,最初的字典 biz_info 看起来是这样的:

biz_info = {
    'business'     : None,
    'name'         : None,
    'neighborhood' : None,
    'address'      : None,
    'city'         : None,
    'state'        : None,
    'zip_code'     : None,
    'latitude'     : None,
    'longitude'    : None,
    'phone'        : None,
    'url'          : None,
    'yelp_url'     : None,
}

然后我像这样执行SQL语句

execute_sql( cur, "insert into " + TABLE_BIZ_NAME + """ values (
                   NULL,
                   %(name)s,
                   %(neighborhood)s,
                   %(address)s,
                   %(city)s,
                   %(state)s,
                   %(zip_code)s,
                   %(latitude)s,
                   %(longitude)s,
                   %(phone)s,
                   %(url)s,
                   %(yelp_url)s,
                   NULL
                   )"""
                   , biz_info )

这样做能防止SQL注入吗?我想用字典来存储信息,因为这样管理起来更简单。

说实话,我甚至不太确定在参数化查询中使用 %,%s%d%()s 之间有什么区别。基本上我只知道不要使用

cursor.execute( "select * from coworkers where name = '%s' and clue > %d" % ( name, clue_threshold ) )

2 个回答

1

你的插入语句最好明确指定要设置的字段名称,这样可以防止因为数据库结构的变化而导致的问题。此外,我觉得你的代码有点重复。我会把插入语句写得更像这样:

cursor.execute \
  (
        "insert into "
    +
        TABLE_BIZ_NAME
    +
        "("
    +
        ", ".join(biz_info.keys())
    +
        ") values ("
    +
        ", ".join(("%s",) * len(biz_info))
    +
        ")",
    biz_info.values()
  )

这样一来,字段名称只需要在创建 biz_info 字典的时候列出一次。将来如果有任何变化,只需要在这里更新就可以了。

3

传递参数给SQL命令字符串的方式取决于你使用的数据库(比如,sqlite使用?作为占位符)。

根据MySQLdb的文档,你可以使用paramstyle这个参数来设置你喜欢的字符串格式方式(可以是format或者pyformat)。

你问题中的第一个例子似乎不被支持。不过,我想说的是,只要你不是像最后一个例子那样格式化整个字符串,你就没问题,因为可以假设查询参数会被正确处理。

撰写回答