使用 `executemany` 更新现有 SQLite3 数据库中的条目(使用 Python sqlite3)

Posted

技术标签:

【中文标题】使用 `executemany` 更新现有 SQLite3 数据库中的条目(使用 Python sqlite3)【英文标题】:Using `executemany` to update entries in an existing SQLite3 database (using Python sqlite3) 【发布时间】:2016-02-21 00:12:43 【问题描述】:

我知道executemany 可用于方便地向数据库添加新条目;与 for 循环中的单个 executes 相比,有助于减少 Python 方法调用开销。但是,我想知道这是否可以与 SQLite 的UPDATE 一起使用。

更具体地说,考虑以下设置:

cnx = sqlite3.connect(DATABASE)
c = cnx.cursor()
for path in paths:
    for data in some_computation(path):
        c.execute("UPDATE TABLENAME SET cont=? WHERE id=?", (data[1], data[0]))
cnx.commit()
cnx.close()

我什至不确定下面的方法是否会更快(必须对其进行基准测试),但问题是它不起作用,因为我认为我做错了。在下面的代码 sn-p 中使用 executemany 来完成我上面发布的任务的任何提示?

cnx = sqlite3.connect(DATABASE)
c = cnx.cursor()

for path in paths:
    data_ids, data_conts = [], []
    for data in some_computation(path):
        if len(data_ids) >= CHUNKSIZE:
            c.executemany("UPDATE TABLENAME SET cont=? WHERE id=?", (data_conts, data_ids))
            cnx.commit()
            data_ids, data_conts = [], []
        data_ids.append(data[0])
        data_conts.append(data[1])
    c.executemany("UPDATE TABLENAME SET cont=? WHERE id=?", (data_conts, data_ids))      
    cnx.commit()

cnx.commit()
cnx.close()

非常感谢您的提示和见解!

编辑 1:

底部示例的问题:

ProgrammingError: Incorrect number of bindings supplied. The current statement uses 2, and there are 50000 supplied.

(其中 CHUNKSIZE=50000)

编辑 2:

同样的错误发生

cnx = sqlite3.connect(DATABASE)
c = cnx.cursor()

for path in paths:
    data_conts = []
    for data in some_computation(path):
        if len(data_ids) >= CHUNKSIZE:
            c.executemany("UPDATE TABLENAME SET cont=? WHERE id=?", (data_conts,))
            cnx.commit()
            data_conts = []

        data_conts.append([data[1], data[0]])
    c.executemany("UPDATE TABLENAME SET cont=? WHERE id=?", (data_conts,))   
    cnx.commit()

cnx.commit()
cnx.close()

但是感谢@falsetru,我注意到了我的错误,应该是

... WHERE id=?", data_conts)

而不是

... WHERE id=?", (data_conts,))

【问题讨论】:

【参考方案1】:

你需要传递一个序列序列([[cont,id], [cont,id], [cont,id], ...],而不是[cont, cont, cont, ...], [id, id, id, ..]):

for path in paths:
    params = []
    for data in some_computation(path):
        if len(data_ids) >= CHUNKSIZE:
            c.executemany("UPDATE TABLENAME SET cont=? WHERE id=?", params)
            cnx.commit()
            params = []
        params.append([data[1], data[0]])
    if params:
        c.executemany("UPDATE TABLENAME SET cont=? WHERE id=?", params)
    cnx.commit()

【讨论】:

谢谢,我之前尝试过类似的方法,但我不小心传递了[[[cont,id], [cont,id], [cont,id], ...]],这就是它不起作用的原因【参考方案2】:

你所拥有的一切都是完美的,除了你应该使用 zip(conts,ids) 其中 conts 和 ids 是列表。这会自动为您重新排列。

【讨论】:

以上是关于使用 `executemany` 更新现有 SQLite3 数据库中的条目(使用 Python sqlite3)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 MySQL executemany 更新 Python 中的列表列表?

Django:使用带有 executemany 和 MySQL 的自定义原始 SQL 插入

在 sql.executemany(... '(' 附近的语法错误

python 在使用 Sql Server 的 fast_executemany 作为 TRUE 时崩溃

我可以将 pyodbc executemany 与 sql 存储过程一起使用吗?

使用 pyODBC 的 fast_executemany 加速 pandas.DataFrame.to_sql