Python 3 SQLite3 - 绑定数量不正确

时间:2015-10-05 10:04:40

标签: python database python-3.x sqlite

我理解Stack Overflow上有很多关于此错误的问题,但我尝试了很多解决方案,显然它们都失败了。

这是一个清单:

sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 74 supplied

SQLite parameter substitution problem

sqlite3.ProgrammingError: Incorrect number of bindings supplied

Reading from database with SQLite and Python: Incorrect number of binding supplied

SQLite Python Insert - Incorrect Number of Bindings Supplied

我正在尝试在SQLite3数据库中存储用户名和哈希密码(由PassLib创建 - https://pythonhosted.org/passlib/)。它们分别存储在变量“targetusername”和“password”中。我的问题是,当我实际尝试将这两个变量插入到名为“Passwords”的数据库表中时,它会出现此错误:

Incorrect number of bindings supplied. The current statement uses 1, and there are 11 supplied.

以下是targetusername和密码将存储的示例:

targetusername = "user4884072"
password = "$5$rounds=535000$ySH31paWMjEDCUUY$jdrBVGsoYnSMkdVBtjCaxQy2f0g3MX1Wts4vSYz7m.4"

此行显示错误:

c.executemany("INSERT INTO {tn} ({idf}, {cn}) VALUES(targetusername, %s" % str(password).\
format(tn="Passwords"))

它已被多次更改以尝试解决问题(这显然是由Python存储变量的方式引起的),但这是最初的原因:

c.execute("INSERT OR IGNORE INTO {tn} ({idf}, {cn}) VALUES (targetusername, password)".\
format(tn="Passwords", idf="Username", cn="Password"))

1 个答案:

答案 0 :(得分:2)

使用c.execute()而不是c.executemany()来插入单行数据。这是您遇到错误的直接原因。

除此之外,不要使用字符串替换,使用参数化查询。这是一个完整的工作示例:

import sqlite3

connection = sqlite3.connect(':memory:')    # in memory database
c = connection.cursor()

c.execute('create table Passwords (Username text, Password text)')

targetusername = "user4884072"
password = "$5$rounds=535000$ySH31paWMjEDCUUY$jdrBVGsoYnSMkdVBtjCaxQy2f0g3MX1Wts4vSYz7m.4"
c.execute('insert into Passwords (Username, Password) values (?, ?)', (targetusername, password))
print c.execute('select * from Passwords').fetchall()

输出:

[(u'user4884072', u'$5$rounds=535000$ySH31paWMjEDCUUY$jdrBVGsoYnSMkdVBtjCaxQy2f0g3MX1Wts4vSYz7m.4')]

在你发布的代码中,没有必要用值替换表名或列名,所以只需将它们放在查询字符串中,如图所示。

这使用参数化查询,其中API将用户名和密码的值插入到?表示的位置的查询中。这比使用字符串替换更安全,因为DB API知道如何正确安全地转义传递给它的值,这可以避免对代码的SQL注入攻击。

它使用execute()而不是executemany(),因为只插入了一行数据。