SQLite参数替换问题

时间:2008-10-23 08:13:37

标签: python sqlite

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

我尝试使用“?”建议参数替换以防止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个绑定。我该如何解决?

8 个答案:

答案 0 :(得分:127)

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

请改用以下表格:

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

Python库参考:sqlite3 Cursor Objects

答案 1 :(得分:51)

我花了半天的时间试图找出为什么这样的事会给我一个错误:

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

只是发现表名无法参数化。希望这会帮助其他人节省一些时间。

答案 2 :(得分:23)

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

>>> ('jason')
'jason'

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

第一个示例改为求值为字符串;所以表示单值元组的正确方法与第二次评估一样。无论如何,下面的代码来修复你的错误。

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

同时将cursor.execute值参数作为字符串给出(这就是你正在做的事情)会导致示例中的第一次评估,并导致你得到的错误。

答案 3 :(得分: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)

答案 4 :(得分:1)

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

  

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

当我这样做时:

  

SELECT fact FROM factoids WHERE key LIKE(?)

而不是:

  

SELECT fact FROM factoids WHERE key LIKE'?'

有效。

这是一些python 2.6的东西吗?

答案 5 :(得分:0)

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

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

您应该执行以下操作:

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

通过使用(item,),你将它变成元组而不是字符串。

答案 6 :(得分:0)

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查询中可以多次使用。

答案 7 :(得分:-5)

尝试

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

你根本不会在?周围包装任何内容,Python sqlite会正确地将它转换为带引号的实体。