【问题标题】:SQLite3 Python: executemany SELECTSQLite3 Python:执行许多选择
【发布时间】:2012-12-18 00:43:53
【问题描述】:

我正在尝试使用 executemany 函数从具有一些 WHERE 约束的一行中取出表中的所有行

import sqlite3

con = sqlite3.connect('test.db')
cur = con.cursor()

cur.execute('CREATE TABLE IF NOT EXISTS Genre (id INTEGER PRIMARY KEY, genre TEXT NOT NULL)')

values = [
        (None, 'action'),
        (None, 'adventure'),
        (None, 'comedy'),
        ]


cur.executemany('INSERT INTO Genre VALUES(?, ?)', values)

ids=[1,2]

cur.executemany('SELECT * FROM Genre WHERE id=?', ids)

rows = cur.fetchall()
print rows

错误

cur.executemany('SELECT * FROM Genre WHERE id=?', ids)
sqlite3.ProgrammingError: You cannot execute SELECT statements in executemany()

【问题讨论】:

    标签: python select sqlite executemany


    【解决方案1】:

    使用execute() 执行返回数据的查询。

    您要么必须使用循环,要么使用 IN (id1, id2, id3) where 子句:

    cur.execute('SELECT * FROM Genre WHERE id in ({0})'.format(', '.join('?' for _ in ids)), ids)
    

    上述表达式为ids 中的每个项目插入一个单独的? 占位符(用逗号分隔)。

    【讨论】:

    • 谢谢Martijin,我不知道IN子句它有很大帮助。
    • cursor.executemany方法是不是重复调用cursor.execute实现的?
    • @shadow0359: 不,cursor.execute() 实际上是通过将参数放入列表然后执行cursor.executemany() 来实现的。请参阅_pysqlite_query_execute functionexecute()executemany() 之间的唯一区别是后者将 multiple 设置为 1)。
    • @MasonSchmidgall 它确实不会创建注入漏洞。它专门生成防止 SQL 注入的SQL 参数。例如。 ids = (42, "Robert'; DROP TABLE Students; --",) 生成查询字符串 SELECT * FROM Genre WHERE id in (?, ?),使用 2 个 SQL 参数执行,数据库安全地引用这些参数作为ids[1] 绝不会作为 SQL 命令执行。
    • @MasonSchmidgall 请仔细阅读此处插入的确切文本。如果要将ids 变量的内容 插入到查询字符串中,那么是的,会有一个漏洞,但是这不是这段代码的作用。我们只是使用序列的length 在这里生成多个? 参数占位符并将那些 放入查询中。 ids 值本身不会被此代码插值,而是作为参数值传递给数据库。
    【解决方案2】:

    你收到的错误信息很简单,You cannot execute SELECT statements in executemany()

    只需更改您的executemany 即可执行:

    ids=[1,2]
    for id in ids:
        cur.execute('SELECT * FROM Genre WHERE id=?', id)
        rows = cur.fetchall()
        print rows
    

    【讨论】:

    • 这也有帮助,但 Martijin 对我的情况更好,不过感谢您的帮助。
    • 这是否涉及为每个 id 重新解析查询?还是 python-sqlite3 缓存它们?
    • @rsaxvc 根据the python documentation,“sqlite3 模块内部使用语句缓存来避免 SQL 解析开销。”对我来说,这意味着它不会每次都重新解析查询。
    猜你喜欢
    • 1970-01-01
    • 2017-05-04
    • 2018-10-09
    • 2010-11-01
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多