2012-09-06 63 views
3

所以我有一堆Python中的數組數據。那麼,我有一個列表清單。我試圖將這個數組存儲到MySQL數據庫中的一個單元中。我試圖使用JSON來序列化我的數據,但也許我不明白JSON是如何工作的。插入Python列表(JSON或其他)到MySQL數據庫

所以連接到我的數據庫後:(我試過LONGTEXT LONGBLOB和數據類型上下游

cur = con.cursor() 
cur.execute("CREATE TABLE IF NOT EXISTS 963168MBV17A(Id INT AUTO_INCREMENT PRIMARY KEY, Rev INT, Part VARCHAR(15), SN INT(7), Date DATE, Time TIME, Iterations INT(3), Upstream LONGBLOB, Downstream LONGBLOB, ResultList LONGTEXT, Result CHAR(1), Report LONGBLOB)") 

我把我的表稱爲upstream_data和downstream_data的列表,並做到:

export_upstream = json.dumps(upstream_data) 
export_downstream = json.dumps(downstream_data) 

然後我執行SQL命令:

cur = con.cursor()  
sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES('503', '100-120970-0031', '1594539', '%s', '%s', '%s', '%s', '%s', 0, P, 0" %(export_date, export_time, export_numtests, export_upstream, export_downstream) 
cur.execute(sql_input) 

引用一個回答[R由Mordi(http://stackoverflow.com/questions/4251124/inserting-json-into-mysql-using-python),我甚至試過:

export_upstream = json.dumps(json.dumps(upstream_data)) 
export_downstream = json.dumps(json.dumps(downstream_data)) 

但不管我最終錯誤:

Traceback (most recent call last): 
    File "P:\Projects\testing database\scrap\test.py", line 83, in <module> 
    cur.execute(sql_input) 
    File "C:\Python27\lib\site-packages\MySQLdb\cursors.py", line 174, in execute 
    self.errorhandler(self, exc, value) 
    File "C:\Python27\lib\site-packages\MySQLdb\connections.py", line 36, in defaulterrorhandler 
    raise errorclass, errorvalue 
ProgrammingError: (1064, "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 '' at line 1") 

而且,當我做了

print "about to execute(%s)" % sql_input 

我看到JSON對象表現爲一個長字符串,有很多單引號的所有的地方(的名單,並在外面代表一個字符串)。當我做了json.dumps(json.dumps(upstream_data))時,內部引號變成了雙引號「」,前面加了\字符。儘管如此,我也遇到了同樣的錯誤。

任何想法?如果沒有,更好的方法來將Python數組/列表數據存儲到單個MySQL單元中?

輸出here

回答

1

你只是以不正確的方式調用數據庫API,如果你用這樣的參數來替換你的參數,那麼你將自己負責數據中的引號和雙引號。

這不僅可以給你tehe錯誤,你有(併爲此幸運),因爲這還允許SQL注入的危險攻擊。

Python的數據庫API是從頭開始設計的,以避免發生這種攻擊的可能性,並且通過讓cursor.execute爲您進行字符串替換來做到這一點。然後它會將必要的轉義添加到您的字符串中。所以,與其做:

sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES('503', '100-120970-0031', '1594539', '%s', '%s', '%s', '%s', '%s', 0, P, 0" %(export_date, export_time, export_numtests, export_upstream, export_downstream) 
cur.execute(sql_input) 

sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES(%s, %s,%s, %s, %s, %s, %s, %s, %s, %s, %s" 
cur.execute(sql_input, [503, '100-120970-0031', '1594539', export_date, export_time, export_numtests, export_upstream, export_downstream, 0, "P", 0]) 

--Still,如果你需要在你的源文件中的所有那些瘋狂的硬編碼的數字,而不是一個自動生成的文件,我敢說你的項目註定要失敗。

+0

工作就像一個魅力,謝謝 – sirgogo

0

我希望這個問題是由於逃避SQL命令,或者說缺乏相同。

永遠不會做到這一點;

cursor.execute("INSERT INTO whatever VALUES (%s)" % "foo") 
從你看到的問題

除此之外,它如果你通過用戶輸入有(查找「小約翰尼表」,如果你不知道爲什麼)是不安全的。

相反,這樣做:

cursor.execute("INSERT INTO whatever VALUES (%s)", ["foo"]) 

而讓MySQL的接口理清逃逸。

6

您需要讓MySQL庫爲您做參數處理;這有讓MySQL的準備你的發言,使得重複插入快過額外的好處:

cur = con.cursor()  
sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES('503', '100-120970-0031', '1594539', ?, ?, ?, ?, ?, 0, P, 0" 
cur.execute(sql_input, (export_date, export_time, export_numtests, export_upstream, export_downstream)) 

Python DB API 2.0 spec對SQL參數化(一些)的更多細節。每個數據庫適配器都記錄了確切支持的參數格式,因此也請檢查。的MySQLdb的模塊,例如,模仿蟒字符串格式化語法,並且使用%s用作佔位符:

sql_input = "INSERT INTO 963168MBV17A(Rev, Part, SN, Iterations, Date, Time, Upstream, Downstream, ResultList, Result, Report) VALUES('503', '100-120970-0031', '1594539', %s, %s, %s, %s, %s, 0, P, 0" 

其它可能的參數選項是數字(:1, :2等),名稱(:foo, :bar)或蟒的其它形式的字符串格式,命名格式說明符:(%(foo)s, %(bar)s)。

+0

謝謝你,完全有幫助。我選擇了jsbueno的答案作爲接受的答案,因爲在sql_input中插入了一些參數,而在執行命令期間傳入了一些參數,導致TypeError(TypeError:並非在字符串格式化期間轉換的所有參數)導致TypeError錯誤。但是,再次感謝,我指出了正確的方向。 – sirgogo

+0

這聽起來像參數的數量和你通過的值之間的不匹配。 –

1

,我與你的代碼中看到的第一個問題是這樣的:

sql_input = "INSERT INTO table (column) VALUES('%s');" % (data) 

你不應該做的 - 你使用字符串插值,它不保護您免受SQL注入攻擊或惡意SQL。

大多數蟒DB API使用的佔位符語法類似於此:

sql = "INSERT INTO table (column) VALUES(%s);" 
values = (data,) 
cur.execute(sql,values) 

請注意,您在聲明和值傳遞分開。 API處理轉義和格式化。

一些將允許類型的字典以及:

sql = "INSERT INTO table (column) VALUES(%(id)s);" 
values = { 'id': 1) 
cur.execute(sql,values) 

閱讀上如何正確使用你的數據庫API - 這是你最大的問題,並可能導致您的所有其他問題。

1

你可能會嘗試的一件事是使用SQLAlchemy的SQL expression generation,它可以處理所有的轉義行爲,並且可以避免處理許多安全漏洞(至少在插入SQL數據庫等方面)。它參數化查詢,而不是像你正在做的那樣進行內聯字符串插值。