python中带变量的SQL查询

2024-05-16 02:52:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在制作一个程序,它是一个小学教师设置的测验的用户界面。我正在尝试使用用户在上一页键入的数据进行此查询。它正在数据库中查找与相关用户名和测验编号匹配的人。这是为了让老师看到学生们在某些测验中的表现。

这是我的密码。

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?


Tags: and用户infrom老师whererowcgi
2条回答

应使用SQL参数:

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

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

引用^{} module documentation

Usually your SQL operations will need to use values from Python variables. You shouldn’t assemble your query using Python’s string operations because doing so is insecure; it makes your program vulnerable to an SQL injection attack (see http://xkcd.com/327/ for humorous example of what can go wrong).

Instead, use the DB-API’s parameter substitution. Put ? as a placeholder wherever you want to use a value, and then provide a tuple of values as the second argument to the cursor’s execute() method. (Other database modules may use a different placeholder, such as %s or :1.)

如果此查询未返回结果,请使用单独的查询向数据库询问其他测验;如果使用OR而不是AND,否则,您将同时获得其他用户已完成的测验结果,此用户已完成的任何操作。

最好的解决方案是使用准备好的语句:

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

在prepared语句模式下,所有变量都被查询文本中的问号替换,并且是execute()的参数。但并不是所有的数据库或数据库驱动程序都支持它。有时,您将不得不使用%s(PostgreSQL驱动程序之一就是这样工作的)。

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

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

相关问题 更多 >