在python中使用变量进行SQL查询

时间:2014-04-22 11:04:42

标签: python sql sqlite variables

我制作的程序是小学教师设置的用户界面。我正在尝试使用上一页上用户输入的数据的查询。它正在寻找数据库中与用户名和测验号相匹配的人。这是老师可以看到学生在某些问题上的表现。

这是我的代码。

dbDatabase = sqlite3.connect('c:\\xampp\\cgi-bin\\MakingATable.db')
cuDatabase = dbDatabase.cursor()

Fieldstorage = cgi.FieldStorage() #what you typed in on the webpage

Quizno = Fieldstorage.getvalue("quizno")
UserID = Fieldstorage.getvalue("username")

#print (Quizno)
#print (UserID)

cuDatabase.execute ("""
    SELECT Result
    FROM resultstable
    WHERE QuizID = '""" + str(Quizno) + """
    AND UserID = '""" + UserID + "'")

for (row) in cuDatabase:
    print (row)

dbDatabase.commit()
cuDatabase.close()

以下是我运行网页时收到的错误消息:

     40         FROM resultstable
     41         WHERE QuizID = '""" + str(Quizno) + """
=>   42         AND UserID = '""" + UserID + "'")
     43 
     44     for (row) in cuDatabase:
AND undefined, UserID = 'HuPa1'


OperationalError: near "HuPa1": syntax error 
      args = ('near "HuPa1": syntax error',) 
      with_traceback = <built-in method with_traceback of OperationalError object>

我还应该使用OR代替AND,这样如果用户没有完成该测验,它将显示用户所做的任何测验。或者如果很多人做过一次测验,那么老师会看到每个人,例如,做过测验1?

2 个答案:

答案 0 :(得分:3)

您应该使用SQL参数:

cuDatabase.execute ("""
    SELECT Result
    FROM resultstable
    WHERE QuizID = ?
    AND UserID = ?""", (Quizno, UserID))

?占位符将被您的值替换,自动引用以防止SQL注入攻击(以及操作错误)。

引用sqlite3 module documentation

  

通常,您的SQL操作需要使用Python变量中的值。你不应该使用Python的字符串操作来组装你的查询,因为这样做是不安全的;它使您的程序容易受到SQL注入攻击(请参阅http://xkcd.com/327/以获取可能出错的幽默示例)。

     

相反,请使用DB-API的参数替换。将?作为占位符放在要使用值的位置,然后提供值元组作为游标execute()方法的第二个参数。 (其他数据库模块可能使用不同的占位符,例如%s:1。)

如果此查询未返回结果,请使用单独的查询向数据库询问其他测验;如果您使用OR而不是AND,则会获得其他用户已完成的quizz结果,任何此< / em>用户已完成。

答案 1 :(得分:0)

最好的解决方案是使用预备声明:

cuDatabase.execute("SELECT Result FROM resultstable WHERE QuizID=? AND UserID=?", Quizno, UserID)

在预准备语句模式下,所有变量都被查询文本中的问号替换,并且是execute()的参数。但并非所有数据库或db驱动程序都支持它。有时候你需要使用%s(PostgreSQL驱动程序中的一个以这种方式工作)而不是问号。

更糟糕,但工作解决方案是使用Python %运算符,但是使用此解决方案,您将不得不使用自己的quote()函数来逃避可能出现在数据中的危险字符(防止SQL注入):

cuDatabase.execute("SELECT Result FROM resultstable WHERE QuizID='%s' AND UserID='%s'" % (quote(Quizno), quote(UserID)))