74

使用 SQLite3 和 Python 2.5,我试图遍历一个列表并根据项目的名称从数据库中提取项目的权重。

我尝试使用“?” 建议使用参数替换来防止 SQL 注入,但它不起作用。例如,当我使用:

for item in self.inventory_names:
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", item)
    self.cursor.close()

我得到错误:

sqlite3.ProgrammingError:提供的绑定数量不正确。当前语句使用 1,提供了 8 个。

我相信这在某种程度上是由数据库的初始创建引起的;我制作的实际创建数据库的模块确实有 8 个绑定。

cursor.execute("""CREATE TABLE Equipment 
    (id INTEGER PRIMARY KEY, 
    name TEXT,
    price INTEGER, 
    weight REAL, 
    info TEXT, 
    ammo_cap INTEGER, 
    availability_west TEXT,
    availability_east TEXT)""")

但是,当我对每个项目名称使用不太安全的“%s”替换时,它工作得很好。像这样:

for item in self.inventory_names:
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = '%s'" % item)
    self.cursor.close()

我不知道为什么当我只调用一个时它认为我有 8 个绑定。我该如何解决?

4

8 回答 8

153

Cursor.execute()方法需要一个序列作为第二个参数。您提供的字符串恰好是 8 个字符长。

请改用以下表格:

self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", [item])

Python 库参考: sqlite3 Cursor Objects

于 2008-10-23T08:41:23.167 回答
74

我花了半天时间试图弄清楚为什么这样的事情会给我一个错误:

cursor.execute("SELECT * from ? WHERE name = ?", (table_name, name))

才发现表名不能参数化。希望这将帮助其他人节省一些时间。

于 2009-02-28T00:32:57.790 回答
30

它的参数cursor.execute表示您需要插入数据库中的值应该是一个元组(序列)。但是考虑这个例子,看看发生了什么:

>>> ('jason')
'jason'

>>> ('jason',)
('jason',)

第一个示例计算结果为字符串;所以表示单值元组的正确方法是在第二次评估中。无论如何,下面的代码可以修复您的错误。

self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", (item,))

还将cursor.execute值参数作为字符串(这就是您正在执行的操作)导致示例中的第一次评估并导致您得到的错误。

于 2011-09-05T08:51:03.867 回答
5

sqlite3模块支持两种类型的参数占位符:

qmark风格

使用一个或多个?来标记每个参数的位置,并提供参数列表或元组。例如:

curs.execute("SELECT weight FROM Equipment WHERE name = ? AND price = ?",
             ['lead', 24])

命名风格

为每个命名参数使用:par占位符,并提供一个字典。例如:

curs.execute("SELECT weight FROM Equipment WHERE name = :name AND price = :price",
             {name: 'lead', price: 24})

命名样式参数的优点是您无需担心参数的顺序,并且每个参数都:par可以在大型/复杂的 SQL 查询中多次使用。

于 2018-07-28T09:47:53.687 回答
2

你试过这个吗?:

for item in self.inventory_names:
    t = (item,)
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", t)
    self.cursor.close()

cursor.execute() 需要一个序列 (list,tuple) 作为第二个参数。(-> ddaa)

于 2008-10-23T08:32:39.330 回答
1

引用(这就是括号的意思吗?)?with parens 似乎对我有用。我一直在尝试(字面意思)'?但我一直在

ProgrammingError:提供的绑定数量不正确。当前语句使用 0,并且提供了 1。

当我这样做时:

SELECT fact FROM factoids WHERE key LIKE (?)

代替:

SELECT fact FROM factoids WHERE key LIKE '?'

有效。

这是一些python 2.6的东西吗?

于 2010-02-10T15:54:12.650 回答
0

items 的每个元素都必须是一个元组。假设名称看起来像这样:

names = ['Joe', 'Bob', 'Mary']

您应该执行以下操作:

for item in self.inventory_names:
self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", (item, ))

通过使用 (item, ) 您将其设为元组而不是字符串。

于 2014-05-19T04:45:45.763 回答
-6

尝试

execute("select fact from factoids where key like ?", "%%s%" % val)

您根本不需要包装任何东西?,Python sqlite 会正确地将其转换为带引号的实体。

于 2010-07-27T18:31:20.773 回答