Python Sqlite3数据库表未更新

时间:2016-09-20 07:36:59

标签: python sqlite

我正在为网站创建一个更改密码页面,该页面会请求新密码和当前密码。使用scrypt库对旧密码进行散列和加密,然后与存储在sqlite3数据库中的密码进行比较,如果这些密码匹配,则对新密码进行哈希处理并更新数据库。但是我在执行update命令时遇到困难,因为它抛出了一个sqlite3.OperationalError:无法识别的标记:“\”错误。 execute语句当前具有以下代码:

c.execute("UPDATE users SET password = \'{0}\' WHERE memberID = \'{1}\'".format(newPas, memID))

最初我们认为这个错误是由于在新密码本身中存在',因此在字符串格式化中使用',所以这又被重新运行:

c.execute("UPDATE users SET password = \"{0}\" WHERE memberID = \"{1}\"".format(newPas, memID))

这成功运行,但实际上并未更改数据库中的任何内容。我们还尝试创建一个查询字符串,然后执行字符串。

query = "UPDATE users SET password = {0} WHERE memberID = {1}".format(newPas, memID)
c.execute(query)

这导致sqlite3.OperationalError:接近“'\ xa1 \ x91 \ x9f \ x88 \ xfb \ x81 \ x12 \ xd4 \ xc2 \ xf9 \ xce \ x91y \ xf0 / \ xe1 *#\ x8aj \ xc7 \ x1d \ XD3 \ X91 \ X14 \ XCB \ XA4 \ xabaP [\ X02 \ X1D \ X1B \ xabr \ xc7 \ XE4 \ XEE \ X19 \ x80c \ x8e | \ xc0S \ xaaX \ XC6 \ X04 \ XAB \ X08 \ x9b \ x8e \ xd7zB \ xc6 \ x84 [\ xfb \ xbc \ x8d \ xfc'“:语法错误。我认为这是由密码中存在'和'字符引起的,但我不确定如何解决这个问题,因为这些是由散列过程添加的,因此删除它们会改变密码。 我想添加的密码是:

b'\xa1\x91\x9f\x88\xfb\x81\x12\xd4\xc2\xf9\xce\x91y\xf0/\xe1*#\x8aj\xc7\x1d\xd3\x91\x14\xcb\xa4\xabaP[\x02\x1d\x1b\xabr\xc7\xe4\xee\x19\x80c\x8e|\xc0S\xaaX\xc6\x04\xab\x08\x9b\x8e\xd7zB\xc6\x84[\xfb\xbc\x8d\xfc'

我想知道是否有人可以分享为什么它不喜欢“\”字符或为什么它不更新数据库的一些见解,并指出我正确的方向使其工作。如果您需要更多信息或代码片段或只是想对我大喊大叫,请不要犹豫!提前谢谢你:)

2 个答案:

答案 0 :(得分:1)

你应该使用这样的参数化查询:

c.execute(&#34;&#34;&#34; UPDATE用户SET密码=?WHERE memberID =?;&#34;&#34;&#34;,(newPas,memID))< / p>

它可以避免SQL注入等令人讨厌的事情。

答案 1 :(得分:0)

您的代码有几点:

  1. 您不应该使用format来构建这样的查询。这使得你可以接受SQL注入,虽然在这种情况下你可能会清理你的输入,但这是一个会咬你的坏习惯。
  2. 所有更改都需要提交到数据库才能真正生效。这就是为什么你的第二个查询没有抛出错误,但同样没有对数据库进行任何更改。
  3. 此查询的正确格式为:

    conn = sqlite3.connect('my_db.db')
    c = conn.cursor()
    
    query = "UPDATE users SET password = ? WHERE memberID = ?"
    c.execute(query, (newPas, memID))
    
    conn.commit() # To finalise the alteration
    

    作为旁注,在这种情况下,游标需要一个元组,因此传递单个值时会出现一个常见的障碍:

    query = "UPDATE users SET password = ? WHERE memberID = 'abc'"
    c.execute(query, (newPas)) # Throws "incorrect number of bindings" error
    
    # Use this instead i.e. pass single value as a tuple
    c.execute(query, (newPas,))
    

    您可以使用format在查询中创建变量字段名称,因为在这种情况下不允许使用占位符:

    fields = ['a', 'b', 'c']
    
    query = "UPDATE users SET {} = ?".format(random.choice(fields))
    

    除了使用它来帮助您构建大型查询,手动键入所有占位符也很繁琐,如果代码更改,很难确保您拥有正确的数字:

    my_list = ['a', 'b',...., n]
    placeholders = ', '.join(['?' for item in my_list])
    
    query = "INSERT .... VALUES = ({})".format(placeholders)