2011-07-28 94 views
1

我使用MySQLdb將大量來自文本文件的數據上傳到MySQL服務器。這工作正常,如果我手動準備一個字符串,如'as', '123', 12, 23,但我無法弄清楚如何循環訪問列表來生成這個,因爲我需要連接字符串和整數。使用MySQLdb將字符串和字符串添加到MySql服務器

,工程的INSERT語句的例子如下:

""" INSERT INTO ACS(ST, CODE, BC001, BC002, BC003) 
VALUES ('AK', '1234567', 20, 30, 40)""" 

這是我試圖生成一個列表這樣的說法:

import MySQLdb 

# sample data 
table = 'TestTable' 
header = ['ST', 'CODE', 'BC001', 'BC002', 'BC003'] 
values = [['AA', '1234567', 20, 30, 40], ['BB', '1234567', 20, 30, 40], ['CC', '1234567', 20, 30, 40],['DD', '1234567', 20, 30, 40]] 


# local SQL server on my computer 
db = MySQLdb.connect (host = 'localhost', user = 'root', passwd = '', db = 'test') 
# prepare a cursor object using cursor() method 
cursor = db.cursor() 

# header columns 
sql1 = '(' 
for i in range(len(header)): 
    sql1 += header[i] + ',' 
sql1 = 'INSERT INTO ' + table + sql1[:-1] + ')' 

# now loop through data values and combine with header each time 
for i in range(len(values)): 

    sql2 = '' 
    for j in range(len(values[i])): 
     sql2 += values[i][j] + ','  #error occurs here 

    # structure: sql2 = """ VALUES ('AA', '1234567', 20, 30, 40)""" 
    sql2 = 'VALUES ' + table + sql2[:-1] + ')'  
    sql = sql1 + sql2 

    try: 
     # Execute the SQL command 
     cursor.execute(sql) 
     # Commit your changes in the database 
     db.commit() 
    except: 
     # Rollback in case there is any error 
     db.rollback() 

# disconnect from server 
db.close() 

該錯誤消息我得到的是

TypeError: unsupported operand type(s) for +: 'int' and 'str' 

我明白爲什麼會發生這種情況,但我無法弄清楚另一種方法生成字符串。有沒有更好的方法來製作這些琴絃?

我在Win7 64位上使用Python27。

+0

對不起,我看着它在谷歌,有沒有這樣的東西作爲pymsql?你可以給主頁鏈接嗎? –

+0

糟糕,我寫了錯誤的包名。它是MySQLdb - 我會更新這個問題;對於那個很抱歉。 – djq

回答

5

MySQLdb已經可以做到這一點,而無需您手動鍵入您的變量。

你想這樣做因爲MySQLdb會自動引用一些東西,並在一定程度上防範SQL注入攻擊。這在任何實際環境中都非常重要,而且如果您打算從事任何專業數據庫工作,則應該採取一些措施。

對於MySQLdb遊標對象,​​命令將自動格式化您的整數,字符串和其他變量,以便它們可以在您的INSERT語句中工作。他們使用一種特殊的格式字符串來做到這一點。

c=db.cursor() 
max_price = 5 
min_price = 1 
c.execute("""SELECT spam, eggs, sausage FROM breakfast 
      WHERE price < %s AND price > %s""", (max_price, min_price)) 

注意兩件事情:首先,所有的變量,無論哪種類型,應在這些特殊的格式字符串作爲%s表示。這只是它的工作方式。其次,​​的第二個參數應該是一個元組,所以如果只有一個變量需要使用,則需要輸入它,如(max_price,)。括號末尾的逗號告訴python它是一個元組。

+0

用於SQL注入保護的+1。 – mcstrother

+0

這絕對是一個更好的方法;我剛剛在上面提到我不瞭解這種方法。我剛剛通過傳遞一個列表來測試它,並注意到MySQL顯示帶有引號''AA'的字符串,而其他方法沒有這樣做(它們只顯示爲「AA」)。我能阻止這種情況的發生嗎? – djq

+0

我們在這裏談論的是什麼MySQL數據類型?我的印象是,所有的字符串都必須用引號括起來。 –

1

您是否嘗試過簡單地將values[i][j]換成str(),如str(values[i][j])

它看起來像你也可以做

sql2 = ','.join([str(x) for x in values[i]]) + ',' 

,如果你想進一步簡化它。 (不知道後面的逗號是必要的,但我把它以符合你的代碼。)

例子:

>>> my_list = ['abc', 1, 2,3, 'do','re','mi'] 
>>> [str(x) for x in my_list] 
['abc', '1', '2', '3', 'do', 're', 'mi'] 
>>> ','.join([str(x) for x in my_list]) 
'abc,1,2,3,do,re,mi' 

在另一方面,如果你需要有最初的字符串包裹的物體在最終的查詢,它看起來像你做單引號,你可能需要做一些像

sql2 = '' 
for x in values[i]: 
    if isinstance(x, basestring): 
     sql2 += "'"+x+"'," 
    else: 
     sql2 += str(x) +"," 
+0

感謝您的建議。我需要能夠三重引用''「」',並且還可以用'''將包含字符串類型的變量包含進來,否則數據庫不會更新。 – djq

+0

對不起,我剛剛注意到第二部分並編輯了我的響應。我不確定你的意思是需要三重報價, – mcstrother

1

正確識別錯誤的其他職位更復雜,但沒有回答你的問題,以更好字符串格式化的方法。

我不確定這是什麼格式,因爲你的代碼有點難以閱讀。你可以看到類似的查詢結束:

INSERT INTO TestTable (ST,CODE,BC001,BC002,BC003) VALUES ('AA','1234567',20,30,40) 

下面是代碼:

sql = (('INSERT INTO {0} ({1}) VALUES ({2})'.format(table, ','.join(header), 
         ','.join(("'" + v + "'" if isinstance(v, str) 
          else str(v)) for v in val))) for val in values) 

然後你只需要做:

for q in sql: 
    try: 
     # Execute the SQL command 
     cursor.execute(q) 
     # Commit your changes in the database 
     db.commit() 
    except: 
     # Rollback in case there is any error 
     db.rollback() 

它增加了引號爲字符串,並使用str.joinstr.format

真的,你應該使用一個參數化查詢,該參數化查詢將關閉的值放入數據庫連接器或數據庫本身的字符串中。

+0

你可能想在'isinstance'調用中使用'basestring'而不是'str',只是爲了增加通用性。傷害鏈接到蟒蛇文檔http://docs.python.org/library/stdtypes.html#str.format – mcstrother

+0

啊!我不知道任何更好的。我剛剛閱讀如何進行參數化查詢,也許我應該這樣做,這是一次性在個人計算機上傳輸大量數據,儘管安全性不是問題 – djq

-1

該錯誤與MySQLdb根本無關。

您正在使用'+'運算符將字符串與整數合併。您的values數組包含混合的字符串和整數,並且您正在使用字符串附加運算符添加它們,該運算符無法用於混合的str和int(您正在執行諸如mystry = 1+','之類的操作)。

針對您的問題的解決方案可以使用str()對來自數組的項目進行操作。像:

sql2 += str(values[i][j]) + ','

+0

但是,他只是在手動逐段格式化字符串,錯誤可能與MySQLdb無關,但如果你看看你會意識到的問題的內容他試圖將一個值列表插入到一行中,這正是他正在使用的函數提供的。 –