Python smartsql编译插入语句

时间:2018-09-09 17:09:23

标签: python python-2.7 sqlite sqlbuilder

我想使用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生成了错误的sql和params: ('(?, (?, ?))', ['INSERT INTO "temp" ("i", "t") VALUES (%s, %s)', 1, 'text']),我得到了错误: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()

1 个答案:

答案 0 :(得分:1)

答案已解决

python doc开始,用于sqlite3 API:

  

通常,您的SQL操作将需要使用Python中的值   变量。您不应该使用Python的字符串来组合查询   操作,因为这样做是不安全的;它使您的程序   容易受到SQL注入攻击(请参阅https://xkcd.com/327/   可能出问题的幽默示例)。

     

请使用DB-API的参数替换。放?作为一个   占位符,只要您想使用一个值,然后提供一个元组   值作为游标的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