SQLite 参数替换和引号
我有一行代码,运行得还不错:
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常量。