mysqldb auto add' '到%s

时间:2017-07-19 13:34:07

标签: python mysql sql

这是我的一段python代码,probe_id是一个字符串:

sql = "select flow_id from t_static_flow where probe_id = %s"                                                                                                                  
cursor = connection.cursor()                                     
cursor.execute(sql, (probe_id, ))                                

效果很好,但是当我将上面的sql更改为

sql = "select flow_id from t_static_flow where probe_id = '%s'"

它给了我这样的错误信息:

(1064,"您的SQL语法中有错误;请查看与您的MySQL服务器版本对应的手册,以便在' 123''&#39附近使用正确的语法39;在第1行")

当我添加''围绕%s,它失败了。但为什么呢?

然后我打开mysql general_log来查看要执行的sql。

2017-07-19T13:21:37.107960Z        85 Query     select flow_id from t_static_flow where probe_id = '123' 

这是我的第一个代码的sql日志,效果很好。

但我认为在第一个代码中最终的sql应该是:

select flow_id from t_static_flow where probe_id = 123

它是如何工作的?

我读了MySQLdb python代码。在执行函数中:

if args is not None:
if isinstance(args, dict):
   query = query % dict((key, db.literal(item))
       for key, item in args.iteritems())
   else:
       query = query % tuple([db.literal(item) for item in args])  

我认为它不像@money那样做额外的工作。

2 个答案:

答案 0 :(得分:1)

根据细节,即使没有在值周围提供单引号,最终查询看起来像是 select flow_id from t_static_flow where probe_id = '123'
值已经有单引号,所以当你明确地在值周围添加单引号时,它会使它像是一样 select flow_id from t_static_flow where probe_id = ''123'' and breaks the query.

答案 1 :(得分:1)

我想我找到了答案。首先感谢@ money的帮助。

在我提到的MySQLdb的执行函数中,它使用 literal 函数来转义字符串。事实上,文字调用C API来解决这个问题。真正的逃避函数是mysql_real_escape_string。在这份文件中,我找到了这样的话:

  

严格地说,MySQL只需要反斜杠,并且用于引用查询中字符串的引号字符将被转义。

以下是我在_mysql.c中找到的单词

  

string_literal(obj) - 将对象obj转换为SQL字符串文字。   这意味着,任何特殊的SQL字符都会被转义,并且会被包含在内   在单引号内。

所以它引用mysql_real_esacep_string()API中的字符串并返回。

因此,在执行的代码中,查询%... 会替换包含单引号的字符串。

和@money说的一样。