2010-06-17 142 views
3
sql = """ 
     INSERT INTO [SCHOOLINFO] 
     VALUES(
      '""" + self.accountNo + """', 
      '""" + self.altName + """', 
      '""" + self.address1 + """', 
      '""" + self.address2 + """', 
      '""" + self.city + """', 
      '""" + self.state + """', 
      '""" + self.zipCode + """', 
      '""" + self.phone1 + """', 
      '""" + self.phone2 + """', 
      '""" + self.fax + """', 
      '""" + self.contactName + """', 
      '""" + self.contactEmail + """', 
      '""" + self.prize_id + """', 
      '""" + self.shipping + """', 
      '""" + self.chairTempPass + """', 
      '""" + self.studentCount + """' 
     ) 
    """; 

我有下面的代碼,Python一直拋出它連接字符串和非類型對象的錯誤。事情是我已經驗證了每個變量這裏實際上是一個字符串,而不是null。今天我一直堅持這一段時間,任何幫助將不勝感激。Python:不能連接str和NoneType對象

+0

打印的東西有可能做的更好(更安全!)的方式。你傳遞這個SQL到什麼庫? MySQLdb的? – 2010-06-17 17:58:46

+3

必需http://xkcd.com/327/學校相關的SQL注入攻擊 – Stephen 2010-06-17 18:00:34

+0

這不知何故讓我想起這個XKCD漫畫(http://xkcd.com/327/),但我希望OP能夠清理他的輸入。 – 2010-06-17 18:01:34

回答

4

改爲使用綁定變量。以下是在Python中使用數據庫的規範:PEP 249: Python Database API Specification v2.0

UPDATE:基於文檔的pymssql,你需要的東西,如:

sql = """ 
    INSERT INTO [SCHOOLINFO] 
    VALUES(
     %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d, %s, %s, %d 
    )""" 
cur.execute(sql, self.accountNo, self.altName, self.address1, self.address2, self.city, self.state, self.zipCode, self.phone1, self.phone2, self.fax, self.contactName, self.contactEmail, self.prize_id, self.shipping, self.chairTempPass, self.studentCount) 
+0

哈是的,我確實消化了我的輸入。這些變量都來自之前的數據庫,當然這已經被消毒了。我正在使用pymssql,因爲我正在使用的人不喜歡MySQL和PHP:( – 2010-06-17 18:27:51

+1

我的建議不是安全相關的。重寫這個以使用綁定變量(假設'pymssql'完成它的工作)將導致更快執行和擺脫像你發佈的奇怪的字符串連接錯誤 – 2010-06-17 18:37:50

+0

我正在看這些綁定變量,但我真的沒有看到我將如何在這段代碼中使用這些變量包含來自數據庫的信息,我我正在插入另一個,而不是進行比較。 – 2010-06-17 18:49:40

0

你不應該串聯值轉換爲SQL語句,因爲這樣做會使你(意外或故意)SQL injection敞開的。相反,您應該將帶有參數標記的SQL語句傳遞給值,並讓數據庫連接器將值插入正確的位置。

所有數據庫連接器都以某種形式支持此功能。例如,psycopg2(下文Python的DB API一個PostgreSQL連接器)會接受這樣的事情:

cursor.execute("insert into schoolinfo (accountno, altname) values (%s, %s)", 
    (self.accountNo, self.altName)) 

做這種方式的一個附帶好處:那不是字符串(如無)值將被自動轉換和你不會得到你在你的問題中描述的錯誤。

1

撰寫的SQL查詢這樣是很危險的,特別是由於sql-injection

如果使用MySqldb一個更好的選擇會是這樣的:

db.query("INSERT INTO [SCHOOLINFO] VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", 
[self.accountNo, self.altName, self.address1, self.address2, self.city, self.state, self.zipCode, self.phone1, self.phone2, self.fax, self.contactName, self.contactEmail, self.prize_id, self.shipping, self.chairTempPass, self.studentCount]) 
1

我要你使用的假設像MySQLdb這樣的庫。處理這些類型的語句,最好的辦法是,像這樣:

import _mysql 

db = _mysql.connect("localhost","user","password","database_name") 
cursor = db.cursor() 

sql = """ 
    INSERT INTO [SCHOOLINFO] 
    VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) 
""" 
cursor.execute(sql, [self.accountNo, self.altName, self.address1, \ 
        self.address2, self.city, self.state, self.zipCode, \ 
        self.phone1, self.phone2, self.fax, self.contactName, \ 
        self.contactEmail, self.prize_id, self.shipping, \ 
        self.chairTempPass, self.studentCount]) 

這樣數據庫庫處理正確的INSERT查詢輸入值。它甚至會使無值作爲NULL輸入到新行中。再加上你這樣做的原始方式很容易受到SQL注入攻擊的影響。

如果您不使用mysql,您的庫可能具有類似的功能。

編輯 -

如果要連接到SQL Server數據庫,使用pyodbc庫。你可以在http://code.google.com/p/pyodbc/。下面的代碼是什麼樣子:

import pyodbc 

conn = pyodbc.connect('DRIVER={SQL Server};SERVER=localhost;DATABASE=database_name;UID=user;PWD=password') 
cursor = conn.cursor() 

sql = """ 
    INSERT INTO [SCHOOLINFO] 
    VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
""" 
cursor.execute(sql, self.accountNo, self.altName, self.address1, \ 
        self.address2, self.city, self.state, self.zipCode, \ 
        self.phone1, self.phone2, self.fax, self.contactName, \ 
        self.contactEmail, self.prize_id, self.shipping, \ 
        self.chairTempPass, self.studentCount) 
conn.commit() 
+0

mssql庫不以此格式喜歡它:( – 2010-06-17 18:56:17

+0

啊,請參閱我的編輯然後 – 2010-06-17 19:08:46

+1

好吧,我會給這一個去。非常感謝你的幫助! – 2010-06-17 19:10:20

2

所有這些問題的答案迄今沒有關注你的問題,但對什麼是正確的做。是的,是的 - 綁定變量更好更安全。是的,使用%格式化速度更快,可能會更好。

但是,在你的問題是什麼給你的錯誤 - 它必須是一個值在某些時候無,沒有其他解釋。只要把一個調試打印在這一方面,是這樣的:

for v in 'accountNo altName address1 address2 city state zipCode phone1 phone2 fax contactName contactEmail prize_id shipping chairTempPass studentCount'.split(): 
    if getattr(self, v) is None: 
     print 'PANIC: %s is None' % v 

我打賭它會在某個時刻;-)

相關問題