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 

我打赌它会在某个时刻;-)

相关问题