SQLite 参数替换问题

79 投票
9 回答
98382 浏览
提问于 2025-04-11 09:28

我在用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个绑定,而我其实只调用了一个。我该怎么解决这个问题呢?

9 个回答

34

在使用 cursor.execute 时,你需要插入到数据库中的值应该用一个元组(序列)来表示。不过看看这个例子,看看发生了什么:

>>> ('jason')
'jason'

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

第一个例子计算出来的是一个字符串;所以正确表示单个值元组的方式是第二个例子那样。不管怎样,下面的代码可以帮你修复这个错误。

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

另外,把 cursor.execute 的值参数作为字符串传入(这正是你现在做的)会导致第一个例子的计算结果,从而出现你遇到的错误。

83

我花了半天的时间在想,为什么像这样的代码会出错:

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

结果发现,表的名字不能用参数来设置。希望这个信息能帮助其他人节省一些时间。

167

Cursor.execute() 方法的第二个参数应该是一个序列(可以理解为一组数据),而你提供的是一个字符串,刚好有8个字符长。

请使用下面的格式:

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

Python库参考:sqlite3 游标对象

撰写回答