2011-06-02 28 views
4

我在使用Python編寫的語句時遇到問題到目前爲止我無法解決這個問題。Python準備好的語句。 SELECT in的問題

查詢,應執行的是例如:

SELECT md5 FROM software WHERE software_id IN (1, 2, 4) 

於是,我就執行這樣的查詢:

software_id_string = "(2, 3, 4)" 
cursor.execute("SELECT md5 FROM software WHERE software_id IN %s", 
       software_id_string) 

的問題是,有'添加到字符串 - >'(2,3,4)',以便查詢將是:

SELECT md5 FROM software WHERE software_id IN ''(2, 3, 4)'' 

我也嘗試重建腳本,如下所示:

software_id_string = " 1 OR software_id = 2" 
cursor.execute("SELECT md5 FROm software WHERE software_id = %s", 
       software_id_string) 

這僅適用於第一個ID,該報告將提交(在這種情況下,1),因爲OR-部分不會被interpeted作爲SQL語句...

有什麼用預先準備好的陳述來解決問題的可能性?

回答

6

您需要在您的參數列表中的每個項目一個佔位符。
您可以使用字符串操作來完成的那部分:

  1. 創建一個%s每個參數,並
  2. 用逗號一起加入的。

在下一步中,您可以按照DB-API documentation中的建議將您的兩個參數傳遞給​​。

software_id_string = (1,2,4) 
qry = '''SELECT md5 
      FROM software 
      WHERE software_id IN (%s)''' % ','.join(['%s']*len(software_id_string)) 
# // 'SELECT md5 FROM software WHERE software_id IN (%s,%s,%s)' 
cursor.execute(qry, software_id_string) 
+0

這是一個很棒的主意!非常感謝你! – pmuens 2011-06-02 16:09:35

0

你想

cursor.execute("SELECT md5 FROM software WHERE software_id IN %s" % software_id_string) 

即一%,而不是逗號

+0

非常感謝您!這是否也會阻止SQL注入?或者它只會將%s替換爲software_id_string? – pmuens 2011-06-02 15:19:39

+0

它只會將%s替換爲software_id_string。 – paulmorriss 2011-06-02 15:23:09

+0

不要太迂腐,但不幸的是這很容易被SQL注入。但即使你只有可信任的輸入,推薦的方法(將單獨的參數傳給'execute()')仍然是可取的,因爲你不必手動管理值的引用,DB-API將免費爲你處理它。由於Adam Bernier的說法,原因是 – bernie 2011-06-02 17:40:24

2

我建議創建一個類型轉換器來顯式處理IN子句。這是psycopg2模塊處理的方式:

from MySQLdb.converters import conversions 

class SQL_IN(object): 
    def __init__(self, seq): 
     self.seq = seq 

    @classmethod 
    def escape(cls, obj, d): 
     return '(' + ','.join((d[type(o)](o, d) for o in obj.seq)) + ')' 

# add this before you call MySQLdb.connect() 
conversions[SQL_IN] = SQL_IN.escape 

真實的例子:

db = MySQLdb.connect() 
cursor = db.cursor() 

SQL = "SELECT * FROM emp WHERE emp_id IN %s" 
in_values = (1, 2, 3) 
cursor.execute(SQL, (SQL_IN(in_values),)) 
print cursor._last_executed 
print cursor.fetchall() 

SQL = "SELECT * FROM emp WHERE name IN %s" 
in_values = ("bob", "fred") 
cursor.execute(SQL, (SQL_IN(in_values),)) 
print cursor._last_executed 
print cursor.fetchall() 

輸出:

SELECT * FROM emp WHERE emp_id IN (1,2,3) 
((1L, 'bob'), (2L, 'larry'), (3L, 'fred')) 
SELECT * FROM emp WHERE name IN ('bob','fred') 
((1L, 'bob'), (3L, 'fred'))