Python SQLite参数替换问题

Python SQLite参数替换问题,python,sqlite,Python,Sqlite,在Python2.5中使用SQLite3,我尝试遍历一个列表,并根据项目名称从数据库中提取项目的权重 我尝试使用建议的“?”参数替换来防止SQL注入,但它不起作用。例如,当我使用: for item in self.inventory_names: self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", item) self.cursor.close() 我得到一个错误: sqlite3.Progra

在Python2.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个

我相信这是由于最初创建数据库造成的;我制作的实际创建DB的模块有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()

我不明白为什么当我只调用一个bindins时它会认为我有8个bindins。我怎样才能修好它?

你试过这个吗

for item in self.inventory_names:
    t = (item,)
    self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", t)
    self.cursor.close()
cursor.execute()需要一个序列(列表、元组)作为第二个参数。(->ddaa)

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

请改用以下表格:

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

Python库参考:sqlite3。

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

cursor.execute("SELECT * from ? WHERE name = ?", (table_name, name))
只是发现表名不能参数化。希望这能帮助其他人节省一些时间。

引用(这就是帕伦斯的意思吗?)?和帕伦斯在一起似乎对我有用。我一直试着用(字面上的)“但是我一直

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

当我这样做的时候:

从factoid中选择事实,其中键类似(?)

而不是:

从factoid中选择事实,其中键类似于“?”

成功了

这是Python2.6吗?

试试看

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

您根本不需要在
周围包装任何内容,Python sqlite将正确地将其转换为带引号的实体。

游标的参数。表示需要插入数据库中的值的execute应该是元组(序列)。然而,考虑这个例子,看看发生了什么:

>>> ('jason')
'jason'

>>> ('jason',)
('jason',)
第一个示例的计算结果改为字符串;因此,表示单值元组的正确方法与第二次求值相同。无论如何,下面的代码可以修复您的错误

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

另外,将
游标.execute
值参数作为字符串(这就是您正在执行的操作)将导致示例中的第一次求值,并导致出现错误。

项的每个元素都必须是一个元组。 假设名称如下所示:

names = ['Joe', 'Bob', 'Mary']
您应该执行以下操作:

for item in self.inventory_names:
self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", (item, ))
通过使用(item,)可以将其设置为元组而不是字符串。

该模块支持两种参数占位符:

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

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

列的数量不是绑定的数量。查询中的“?”数是绑定数。是的,我知道。我只是觉得代码试图使用“createtable”语句引用的绑定。我不知道它指的是项目本身中的字母数?根本不应该引用,也就是说,
从factoid中选择事实,其中key LIKE?
。恰好在SQL中添加括号不会改变其含义,因此
从factoid中选择事实,其中key LIKE(?)
等同于不带()。如果您使用的是Django,并且您的查询是
从factoid中选择事实,其中key LIKE“%s”
,那么您还需要避免引号
cursor.execute()
不会将%s识别为该查询中的绑定。因此,请使用
cursor.execute(“从factoid中选择事实,其中键类似于%s”,(键名称),)
您可以执行如下操作:
cursor.execute(“从%s中选择*,其中名称=?”%table\u name,(名称),)
,尽管这可能会使您的程序容易受到SQL注入攻击。对于用户输入决定表的情况,我从dict中提取表名,如果输入的内容是意外的,则引发异常。可能不是最好的方法,但似乎不太容易导致SQL注入。@James我很好奇,在什么情况下,您需要根据用户输入更改要插入的表?在这种情况下,使用dict听起来是个不错的主意,每当我使用switch语句时,我都会使用它。@num1:任何时候你想要有一个以表名作为class init()参数的泛型类。因此,您不想硬编码表名,而是让它成为一个变量……您对表、字段名使用
[]
,对值使用
,@Kirk,但参数替换对sqlite表名不起作用,因此上面的一个是正确的。这将生成大量查询。N+1问题。不知何故,我有一个完整的编辑队列,所以我留下一条评论供编辑。--cursor.execute函数接受3个参数:查询字符串、iterable项列表、开关。在这里,单个项目的项目列表可以使用“[item]”或“(item,)”——接受的答案只是另一种形式的解决方案,这是另一种@Proofit404,不同的paramstyle选项如何?sqlite3支持哪一个,它是在哪里编写的?