如何在SQLite中为多行返回插入的id?

时间:2016-10-05 13:35:06

标签: sqlite

给出一张表:

CREATE TABLE Foo(
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    Name TEXT
);

如何使用以下命令返回同时插入的多行的ID:

INSERT INTO Foo (Name) VALUES
('A'),
('B'),
('C');

我知道last_insert_rowid()但我没有找到任何将它用于多行的示例。

我想要实现的目标可以在 SQL Server 示例中看到:

DECLARE @InsertedRows AS TABLE (Id BIGINT);
INSERT INTO [Foo] (Name) OUTPUT Inserted.Id INTO @InsertedRows VALUES 
    ('A'),
    ('B'),
    ('C');
SELECT Id FROM @InsertedRows;

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

给出SQLite3 locking

  

需要EXCLUSIVE锁才能写入数据库文件。文件上仅允许一个EXCLUSIVE锁,并且不允许任何其他类型的锁与EXCLUSIVE锁共存。为了最大化并发性,SQLite致力于最小化持有EXCLUSIVE锁的时间。

Last Insert Rowid的工作方式:

  

...将最近成功执行INSERT的rowid返回到数据库连接D上的rowid表或虚拟表中。

应该安全地假设,当编写器将其批处理INSERT执行到ROWID表时,没有其他编写器可以使生成的主键不再是必需的。因此,插入主键为[lastrowid - rowcount + 1, lastrowid]。或在Python SQLite3 API中:

cursor.execute(...)  # multi-VALUE INSERT
assert cursor.rowcount == len(values)
lastrowids = range(cursor.lastrowid - cursor.rowcount + 1, cursor.lastrowid + 1)

通常情况下,如果您不混合使用提供的密钥和预期生成的密钥,或者不使用AUTOINCREMENT模式的文档说明:

  

只要您从未使用最大ROWID值并且从未删除具有最大ROWID的表中的条目,上述普通ROWID选择算法将生成单调递增的唯一ROWID。

以上内容应该可以正常工作。

Python script可用于测试上述内容在多线程和多进程设置中的正确性。

其他数据库

例如,MySQL InnoDB(至少在默认的innodb_autoinc_lock_mode = 1“连续”锁定模式下)以类似的方式工作(尽管显然在更多并发条件下),并保证可以从{{1}推断出插入的PK。 }:

  

“简单插入”(预先知道要插入的行数)可以通过在互斥锁(浅色的控制)下获取所需的自动递增值数量来避免表级AUTO-INC锁定。权重锁定)仅在分配过程中才保持有效,直到语句完成为止

答案 1 :(得分:1)

这是不可能的。如果要获得三个值,则必须执行三个INSERT语句。