2014-02-12 43 views
23

在運行此腳本: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

回答

53

取而代之的是:

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要求你作爲一個序列傳遞任何參數。' –

12

你可以試試這個代碼:

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

你可以看到the documentation

+3

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

+0

您不應該在佔位符周圍手動引用。 –

4

'%' 的關鍵字是非常危險的,因爲 '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) 
0

我不明白前兩個答案。我認爲他們必須是版本依賴的。我無法在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

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

我不是爲什麼,但這對我有用。而不是使用'%s'

0

據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必須的參數列表。

願這幫助你。

相關問題