在SQLite中使用UPDATE为Python列表中的许多行

时间:2017-01-27 16:44:45

标签: python sqlite

我使用与Python接口的SQLite(sqlite3)来保存用于处理大量数据的表中的参数。假设我最初已经填充了表,但随后更改了参数,我想更新我的表。如果我创建一个包含更新参数的Python列表,对于表中的每一行和每列,如何更新表?

我看过herehere(虽然后者指的是C ++而不是Python)但这些并没有真正回答我的问题。

为了具体说明,我在下面展示了一些代码:

import sqlite3 as sql
import numpy as np

db = sql.connect('./db.sq3')
cur = db.cursor()

#... Irrelevant Processing Code ...#

cur.execute("""CREATE TABLE IF NOT EXISTS process_parameters (
                 parameter_id            INTEGER PRIMARY KEY,
                 exciton_bind_energy     REAL,
                 exciton_bohr_radius     REAL,
                 exciton_mass            REAL,
                 exciton_density_per_QW  REAL,
                 box_trap_side_length    REAL,
                 electron_hole_overlap   REAL,
                 dipole_matrix_element   REAL,
                 k_cutoff                REAL)""")

#Parameter list
process_params = [(E_X/1.6e-19, a_B/1e-9, m_exc/9.11e-31, 1./(np.sqrt(rho_0)*a_B), D/1e-6, phi0/1e8, d/1e-28, k_cut/(1./a_B)) for i in range(0,14641)]

#Check to see if table is populated or not
count = cur.execute("""SELECT COUNT (*) FROM process_parameters""").fetchone()[0]

#If it's not, fill it up
if count == 0:
    cur.executemany("""INSERT INTO process_parameters VALUES(NULL, ?, ?, ?, ?, ?, ?, ?, ?);""", process_params)
    db.commit()

现在,假设在后续处理运行中,我更改了process_params中的一个或多个参数。我想要的是在Python将使用最新版本的参数更新数据库的任何后续运行中。所以我做了

else:
    cur.executemany("""UPDATE process_parameters SET exciton_bind_energy=?, exciton_bohr_radius=?, exciton_mass=?, exciton_density_per_QW=?, box_trap_side_length=?, electron_hole_overlap=?, dipole_matrix_element=?, k_cutoff=?;""", process_params)
    db.commit()
db.close()

但是当我这样做时,脚本似乎挂起(或者进展得很慢),这样Ctrl + C甚至不会退出脚本(通过ipython运行)。

我知道在这种情况下,使用庞大的Python列表进行更新可能无关紧要,但这是我想澄清的原则,因为在另一个时间,我可能不会更新具有相同值的每一行。如果有人能帮我理解正在发生的事情和/或如何解决这个问题,我真的很感激。感谢信。

1 个答案:

答案 0 :(得分:2)

cur.executemany("""
    UPDATE process_parameters SET 
        exciton_bind_energy=?, 
        exciton_bohr_radius=?, 
        exciton_mass=?, 
        exciton_density_per_QW=?, 
        box_trap_side_length=?, 
        electron_hole_overlap=?, 
        dipole_matrix_element=?,
        k_cutoff=?
   ;
""", process_params)

您在更新时忘记了WHERE子句。如果没有WHERE子句,UPDATE语句将更新表中的每个行。由于您提供了14641组参数,因此SQLite驱动程序将更新14641(输入)×14641(表中的行)= 2.14亿次的行,这表明它的速度很慢。

正确的方法是每次只更新相关行:

cur.executemany("""
    UPDATE process_parameters SET 
        exciton_bind_energy=?, 
        exciton_bohr_radius=?, 
        exciton_mass=?, 
        exciton_density_per_QW=?, 
        box_trap_side_length=?, 
        electron_hole_overlap=?, 
        dipole_matrix_element=?,
        k_cutoff=?
   WHERE parameter_id=?        
-- ^~~~~~~~~~~~~~~~~~~~ don't forget this
   ;
""", process_params)

当然,这意味着process_params必须包含参数ID,您还需要修改INSERT语句以插入参数ID。