【问题标题】:SQLite get id and insert when using executemanySQLite在使用executemany时获取id并插入
【发布时间】:2015-04-29 04:04:10
【问题描述】:

我正在优化我的代码,并减少查询量。这些曾经是一个循环,但我正在尝试重组我的代码来完成这样的工作。如何让第二个查询工作,以便它使用在每行的第一个查询中输入的 id。假设数据集的顺序也正确。

self.c.executemany("INSERT INTO nodes (node_value, node_group) values (?, (SELECT node_group FROM nodes WHERE node_id = ?)+1)", new_values)
#my problem is here
new_id = self.c.lastrowid
connection_values.append((node_id, new_id))
#insert entry
self.c.executemany("INSERT INTO connections (parent, child, strength) VALUES (?,?,1)", connection_values)

这些查询曾经是一个 for 循环,但耗时太长,所以我试图避免使用 for 循环并单独执行查询。我相信他们可能是将其组合到一个查询中的一种方式,但我不确定如何做到这一点。

【问题讨论】:

  • 你的意思是像insert into table_1 (x) values (y); set @last_id = last_insert_id(); insert into table_2 ( z ) values ( @last_id ); 这样的东西吗?
  • 没错,但是executemany只允许运行我刚刚发现的一条语句

标签: python sql sqlite python-3.x


【解决方案1】:

您需要一次插入一行,或者读回 SQLite 的 ID 分配逻辑选择的 rowid;正如Autoincrement in SQLite 中所述,不能保证生成的 ID 是连续的,尝试在客户端代码中猜测它们是一个坏主意。

如果您的程序是单线程的,您可以隐式执行此操作,如下所示:

在表定义中设置 AUTOINCREMENT 关键字。这将保证任何生成的行 ID 都高于当前表中出现的任何行 ID。

  1. 在第一条语句之前,确定表中使用的最高 ROWID。

    oldmax ← 执行("SELECT max(ROWID) from nodes")。

  2. 像以前一样执行第一次插入。

  3. 读回使用 select 语句实际分配的行 ID:

    NewNodes ← 执行("SELECT ROWID FROM nodes WHERE ROWID > ? ORDER BY ROWID ASC", oldmax) .

  4. 通过组合new_values 的父ID 和NewNodes 的子ID 来构造connection_values 数组。

  5. 像以前一样执行第二次插入。

这可能会也可能不会比您的原始代码更快; AUTOINCREMENT 会降低性能,如果不实际进行实验,则无法判断。

如果您的程序正在从多个线程写入 nodes,您需要使用互斥锁来保护该算法,因为它对于多个并发写入者根本不起作用。

【讨论】:

    猜你喜欢
    • 2019-07-10
    • 2018-08-07
    • 2021-04-10
    • 1970-01-01
    • 2011-04-14
    • 2010-10-25
    • 2012-02-12
    • 1970-01-01
    相关资源
    最近更新 更多