2015-09-29 38 views
3

我有一系列SQL select語句,需要使用MySQLdb從Python腳本運行。我想傳遞給select語句的變量之一是unit_ids。我已經嘗試將unit_ids作爲字符串以及字符串元組對待。最初,反斜槓被插入到字符串中。在網上瀏覽後,我可以避開反斜槓,但是現在插入了額外的引號。這裏是我當前的代碼:如何防止從Python插入到MySQLdb語句中的額外引號?

connection = MySQLdb.connect('localhost', 'root', '*****', 'test') 
cur = connection.cursor 

unit_ids = ('0A1', '0A2', '0A3', '0A4') 
attr = 'sample' 

cur.execute("""SELECT COUNT(*) FROM test WHERE attribute = %s AND unit_id IN %r""", (a, tuple(unit_ids))) 

使用cur._last_executed,我可以看到,被執行的實際SQL語句是:

SELECT COUNT(*) FROM test WHERE attribute = 'sample' AND unit_id IN ("'0A1'", "'0A2'", "'0A3'", "'0A4'") 

任何想法,我需要什麼,纔能有('0A1', '0A2', '0A3', '0A4')有待改變在SQL語句中保持不變?

更新:這是確切的輸出使用%s當我報復:

>>> cn = MySQLdb.connect('localhost', 'root', '***', '***') 
>>> c = cn.cursor() 
>>> unit_ids = ('0A1', '0A2', '0A3', '0A4') 
>>> a = 'foo' 
>>> c.execute("""select count(*) from model_test where attribute = %s and unit_id in %s""", (a, unit_ids)) 
1L 
>>> print(c._last_executed) 
select count(*) from model_test where attribute = 'foo' and unit_id in ("'0A1'", "'0A2'", "'0A3'", "'0A4'") 

在這一點上,我想我可能只需要爲unit_ids每個元素(如unit_id1 = '0A1')創建單獨的變量。順便說一句,我使用Python 2.7.9和MySQL Server 5.6。



更新2:@thebjorn解決了它:我的MySQLdb版本已過時。升級後,沒有更多的額外引號被插入到SQL語句中。

+0

也許嘗試:'unit_ids = '( 「0A1」, 「0A2」, 「0A3」, 「0A4」)'' –

+0

這是有趣的。 'print(「」「SELECT COUNT(*)FROM test WHERE attribute =%s AND unit_id IN%r」「」,(a,tuple(unit_ids)))'對我有用,'cur.execute'應該符合相同的語法。 –

+0

或者在執行字符串中添加尾部逗號並僅使用unit_ids而不是元組(unit_ids) – carruthd

回答

1

你不需要任何魔法,只是做普通的mysql方式:

connection = MySQLdb.connect('localhost', 'root', '*****', 'test') 
cur = connection.cursor() 

unit_ids = ('0A1', '0A2', '0A3', '0A4') 
attr = 'sample' 

cur.execute("""SELECT COUNT(*) FROM test WHERE attribute = %s AND unit_id IN %s""", (a, unit_ids)) 

我能看到的唯一的皺紋,如果a是不包括在內,unit_ids只有一個項目,那麼元組語法可能會讓你失望。如果您unit_ids到一個列表,然後語法將不會非常尷尬:

unit_ids = ('0A1',) 
cur.execute("SELECT COUNT(*) FROM test WHERE unit_id IN %s", (unit_ids,)) 

其中內聯時,就變成了:

cur.execute("SELECT COUNT(*) FROM test WHERE unit_id IN %s", (('0A1',),)) 

使用對比列表(一個參數,該參數是一個項目列表):

cur.execute("SELECT COUNT(*) FROM test WHERE unit_id IN %s", [['0A1']]) 

可以使用%s爲所有的MySQL參數(少數人可得使用,但不能%r - 這是不是我的字符串nterpolation)。

更新:,你必須做一些不同從我..這裏是cursor._last_executed

>>> cn = MySQLdb.connect('server', 'user', 'password', 'database') 
>>> c = cn.cursor() 
>>> unit_ids = ('0A1', '0A2', '0A3', '0A4') 
>>> c.execute("select count(*) from foo where id in %s", (unit_ids,)) 
Traceback (most recent call last): 
    File ... 
_mysql_exceptions.ProgrammingError: (1146, "Table 'djangodevelop.foo' doesn't exist") 
>>> c._last_executed 
"select count(*) from foo where id in ('0A1','0A2','0A3','0A4')" 
>>> 
+0

如果我在第一個代碼塊中運行代碼,然後添加'print(cur._last_executed)'行以顯示確切的SQL語句發送到數據庫,我仍然看到...... AND unit_id IN(「'0A'」,「'0A2'」,「'0A3'」,「'0A4'」)''。代碼起作用,因爲它不會引發錯誤,但'unit_ids'中每個元素周圍的附加引用會導致select語句不正確。 – zkstine

+0

我沒有得到額外的引號(請參閱更新後的答案)。你是否記得要將'%r'改爲'%s'? – thebjorn

+0

@zkstine你正在使用錯誤的參數'%r'。建立查詢時不要使用它。檢查我的答案。 – FallenAngel

0

的輸出不要在unit_id IN %r使用%r。在構建SQL查詢時,Python-Mysql數據庫API僅支持%s作爲佔位符。

From the docs

在前面的例子中,我們存儲在變量查詢中的SELECT語句。請注意,我們正在使用未加引號的%s標記,其日期應該是。連接器/ Python將hire_start和hire_end從Python類型轉換爲MySQL可以理解的數據類型並添加所需的引號。在這種情況下,它將用'1999-01-01'替換第一個%s,用'1999-12-31'替換第二個%s。

您可以在Python-MySql docs中看到類似的警告和用法。

cur.execute(""" 
    SELECT COUNT(*) FROM test WHERE attribute = %s AND unit_id IN %s 
""", (a, ('0A1', '0A2', '0A3', '0A4'))) 
+0

感謝您花時間回覆@FallenAngel。 @thebjorn已經指出我需要使用'%s'而不是'%r'。現在我只想將整個變量'unit_ids'傳遞給SQL語句,而不是顯式地傳遞每個元素,但是當我這樣做時,每個元素周圍會插入額外的引號。 – zkstine