SQLite 参数替换和引号

11 投票
6 回答
21334 浏览
提问于 2025-04-15 12:18

我有一行代码,运行得还不错:

c.execute('select cleanseq from cleanseqs WHERE newID="%s"'%name)

但我想用SQLite的参数替换,而不是字符串替换(因为我看到这里说这样更安全)。

这是我尝试的(失败的)代码:

t = (name,)
c.execute('select cleanseq from cleanseqs WHERE newID="?"',t)

但是这行代码返回了:

'提供的绑定数量不正确。 当前语句使用了 0,而提供了1.'

所以我语句的左边部分没有工作。我提供了一个绑定(在t中的name),但看起来问号(?)没有被解析。如果我删除问号周围的引号,它就能工作。但我想保留引号,因为我记得有些情况下是需要它们的。

所以问题是:我该如何转换这一行:

c.execute('select cleanseq from cleanseqs WHERE newID="%s"'%name)

6 个回答

15

我觉得用命名参数的方式更容易读懂,而且 sqlite3 也支持这种写法:

c.execute('SELECT cleanseq FROM cleanseqs WHERE newID=:t', locals())

注意:用 {'t': t}dict(t=t) 代替 locals() 会更严格地说是正确的,但我觉得这样会影响可读性,特别是当参数很多或者名字比较长的时候。总之,我觉得 :t? 更好;-)。

22

对于像我一样找到这个话题并感到非常沮丧的人,因为有些人忽视了有时候你不能简单地忽略引号(比如你在使用LIKE命令时),你可以通过做一些类似下面的事情来解决这个问题:

var = name + "%"
c.execute('SELECT foo FROM bar WHERE name LIKE ?',(var,))

这样做可以让你在这种情况下使用通配符。

10

关于“如果我删除问号周围的引号,它就能工作。但我想保留引号,因为我记得有些情况下我需要它们。”

你之前在自己构建整个SQL语句时的记忆并不重要。

现在的做法是:在SQL语句中每个需要替换的地方用问号“?”标记,然后传入一个元组,每个问号对应一个值——就这么简单;这个包装器会自动给任何字符串加上引号,确保它们是有效的SQL常量。

撰写回答