我想使用sqlbuilder (https://sqlbuilder.readthedocs.io/en/latest/)库来构建对sqlite的原生查询。这是我插入数据的代码:
import sqlite3
from sqlbuilder.smartsql import Q, T
from sqlbuilder.smartsql.dialects.sqlite import compile
if __name__ == '__main__':
connection = sqlite3.connect(':memory:')
with connection:
connection.execute('CREATE TABLE temp (t TEXT, i INTEGER)')
insert = compile(Q(T.temp).insert({T.temp.t: 'text', T.temp.i: 1}))
sql, params = insert
connection.execute(
sql, params
)
connection.close()此代码不起作用,因为compile为sqlite:('(?, (?, ?))', ['INSERT INTO "temp" ("i", "t") VALUES (%s, %s)', 1, 'text'])生成了不正确的sql和params,而我得到了错误:sqlite3.OperationalError: near "(": syntax error。
有趣的是,编译和执行select语句没有问题。
更新:
select语句的代码及其工作:
import sqlite3
from sqlbuilder.smartsql import Q, T
from sqlbuilder.smartsql.dialects.sqlite import compile
if __name__ == '__main__':
connection = sqlite3.connect(':memory:')
with connection:
connection.execute('CREATE TABLE temp (t TEXT, i INTEGER)')
select = compile(Q(T.temp).fields('*'))
print(select) # ('SELECT * FROM `temp`', [])
sql, params = select
connection.execute(
sql, params
)
connection.close()发布于 2018-09-10 18:12:07
修正的答案
来自python for sqlite3 API:
通常,您的SQL操作将需要使用Python变量的值。您不应该使用Python的字符串操作组装查询,因为这样做是不安全的;它使您的程序容易受到SQL注入攻击(有关可能出错的幽默示例,请参见https://xkcd.com/327/ )。 相反,使用DB的参数替换。放?作为占位符,可以在任何地方使用值,然后提供一个值元组作为游标的execute()方法的第二个参数。(其他数据库模块可能使用不同的占位符,如%s或:1)例如: #永远不要这么做--不安全!
symbol = 'RHAT' c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)#代替这样做t = ('RHAT',) c.execute('SELECT * FROM stocks WHERE symbol=?', t)
insert` `('(?, (?, ?))', ['INSERT INTO "temp" ("i", "t") VALUES (%s, %s)', 1, 'text'])的返回值表示sqlbuilder正在尝试接受此建议。剩下的是如何进行字符串内插,以将其转换为有效的sqlite语法。原来,result构造函数的Q参数就是这样做的。
insert = Q(T.temp,result=Result(compile=compile)).insert({T.temp.t: 'text', T.temp.i: 1})将返回一个元组,即“SQL现成”,即:('INSERT INTO `temp` (`i`, `t`) VALUES (?, ?)', [1, 'text'])。现在,您看到‘'%s’已被'?‘所取代。不要忘记导入Result。
https://stackoverflow.com/questions/52246833
复制相似问题