Python的MySQLdb的类型错误:不是所有的参数字符串转换期间格式化

问题描述:

在运行此脚本:Python的MySQLdb的类型错误:不是所有的参数字符串转换期间格式化

#! /usr/bin/env python 
import MySQLdb as mdb 
import sys  

class Test: 
    def check(self, search): 
     try: 
      con = mdb.connect('localhost', 'root', 'password', 'recordsdb'); 

      cur = con.cursor() 
      cur.execute("SELECT * FROM records WHERE email LIKE '%s'", search) 

      ver = cur.fetchone() 

      print "Output : %s " % ver 

     except mdb.Error, e: 

      print "Error %d: %s" % (e.args[0],e.args[1]) 
      sys.exit(1) 

     finally:  
      if con:  
       con.close() 

test = Test() 
test.check("test") 

我得到的错误:

./lookup 
Traceback (most recent call last): 
    File "./lookup", line 27, in <module> 
    test.check("test") 
    File "./lookup", line 11, in creep 
    cur.execute("SELECT * FROM records WHERE email LIKE '%s'", search) 
    File "/usr/local/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 187, in execute 
    query = query % tuple([db.literal(item) for item in args]) 
TypeError: not all arguments converted during string formatting 

我零知道为什么。我试图做参数化查询,但它只是一个痛苦。我对Python有点新鲜,所以这可能是一个明显的问题。

+2

不需要/希望引用您的查询参数。 –

+1

即'cur.execute(“SELECT * FROM records WHERE email LIKE%s”,[search])' –

+0

我在使用python2.7时遇到了这个问题,但是在使用python2.6时是正确的。你知道原因吗? – Matt

取而代之的是:

cur.execute("SELECT * FROM records WHERE email LIKE '%s'", search) 

试试这个:

cur.execute("SELECT * FROM records WHERE email LIKE '%s'", [search]) 

见MySQLdb的documentation。原因在于execute的第二个参数表示要转换的对象的列表,因为您可以在参数化查询中拥有任意数量的对象。在这种情况下,你只有一个,但它仍然需要是一个可迭代的(一个元组而不是一个列表也可以)。

+0

我明白了,所以必须通过一个列表才能使其工作? –

+0

另外有趣的是,我仍然可以在输入中传递%,它不会转义它,而是会像通配符一样使用它 –

+0

@MandatoryProgrammer不会使用'%'格式化查询字符串。使用上面的方法。并从文档'的DB API要求你作为一个序列传递任何参数。' –

你可以试试这个代码:

cur.execute("SELECT * FROM records WHERE email LIKE '%s'", (search,)) 

你可以看到the documentation

+3

在元组末尾添加逗号正是我所需要的。 – User

+0

您不应该在占位符周围手动引用。 –

'%' 的关键字是非常危险的,因为 'SQL注入攻击' 的是主要原因。
所以你只是使用这段代码。

cursor.execute("select * from table where example=%s", (example,)) 

t = (example,) 
cursor.execute("select * from table where example=%s", t) 
如果你想尝试插入到表

,试试这个。

name = 'ksg' 
age = 19 
sex = 'male' 
t = (name, age, sex) 
cursor.execute("insert into table values(%s,%d,%s)", t) 

我不明白前两个答案。我认为他们必须是版本依赖的。我无法在Ubuntu 14.04LTS附带的MySQLdb 1.2.3上重现它们。让我们尝试一下。首先,我们验证MySQL不接受双撇号:

mysql> select * from methods limit 1; 
+----------+--------------------+------------+ 
| MethodID | MethodDescription | MethodLink | 
+----------+--------------------+------------+ 
|  32 | Autonomous Sensing | NULL  | 
+----------+--------------------+------------+ 
1 row in set (0.01 sec) 

mysql> select * from methods where MethodID = ''32''; 
ERROR 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 '9999'' ' at line 1 

没有。让我们尝试使用/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py中的查询构造函数发布的强制性示例,其中我打开“con”作为与数据库的连接。

>>> search = "test" 
>>> "SELECT * FROM records WHERE email LIKE '%s'" % con.literal(search) 
"SELECT * FROM records WHERE email LIKE ''test''" 
>>> 

不,双撇号导致它失败。让我们尝试迈克·格雷厄姆的第一个评论,他建议离开过撇号引述%S:

>>> "SELECT * FROM records WHERE email LIKE %s" % con.literal(search) 
"SELECT * FROM records WHERE email LIKE 'test'" 
>>> 

是的,这将工作,但麦克的第二意见和文档说参数执行(由CON处理。文字)必须是一个元组(search,)或列表[search]。你可以尝试它们,但你会发现上面的输出没有什么不同。

最好的答案是ksg97031's。

+0

ksg97031也使用元组。这与MySQLdb库相关,而不是MySQL本身。 – adonese

cur.execute("SELECT * FROM records WHERE email LIKE %s", (search,)) 

我不是为什么,但这对我有用。而不是使用'%s'

据PEP8,我更喜欢用这种方式来执行SQL:

cur = con.cursor() 
# There is no need to add single-quota to the surrounding of `%s`, 
# because the MySQLdb precompile the sql according to the scheme type 
# of each argument in the arguments list. 
sql = "SELECT * FROM records WHERE email LIKE %s;" 
args = [search, ] 
cur.execute(sql, args) 

这样,你将认识到,第二个参数execute方法args必须的参数列表。

愿这帮助你。