SQLite UPSERT 并获取插入或更新的 rowid

问题描述 投票:0回答:1

我有一个存储目录路径(Dirs)的表。这些目录行由 Files 表引用,使用目录的 rowid 作为外键。重新索引目录/文件时,需要检查它们是否已经存在并根据需要插入/更新。添加目录路径后,目录中的文件将进行额外的插入/更新,因此需要目录的行 ID。为了优化,我想尝试插入目录并在冲突时(已在目录表中)更新可能已更改的其他字段。但是,我还需要目录的 rowid,无论它们是插入还是更新。

我首先尝试了 REPLACE,但它有一个不幸的副作用,即它更改了 rowid,从而破坏了现有文件和目录的外键关系。

当我遇到 UPSERT 操作的概念时,我最初很兴奋,因为我认为它会做我想要的事情。然而,经过大量研究,我得出的结论是,当前的 SQLite3 无法在发生 UPDATE 时通过“INSERT .. ON CONFLICT UPDATE ..”获取受影响的 rowid,而无需使用额外的 SELECT 语句来检索 ID目录名称。因此,当额外的插入需要插入/更新的 rowid 时,此功能有些无用。它可能执行的一项改进是通过使用 C API 函数 sqlite3_set_last_insert_rowid() 将最后一个插入 rowid 设置为 0 来检测是否发生 INSERT 或 UPDATE,如果发生 INSERT,则无需执行 SELECT,因为调用可以使用C API sqlite3_last_insert_rowid(),如果它不为0,则它是INSERT的rowid。

这是一个遗憾,因为 SQLite 显然知道 UPSERT 操作刚刚更新的行的 rowid,但无法使其可用。也许是对未来版本的一个很好的功能请求。可以将其存储到last_insert_rowid,因为在插入时它无论如何都会被设置。

如果其他人有更好的方法来实现这一点,我很想听听。

sql sqlite upsert
1个回答
0
投票

您的评估是正确的,即 SQLite 没有直接提供在 UPSERT 操作中检索更新行的 rowid 的方法。

您可以采取其他方法来实现您的目标。

  1. 使用带有
    INSERT
    子句的
    ON CONFLICT
    语句,该子句将在记录已存在时更新记录。
  2. INSERT
    UPDATE
    语句之后,执行
    SELECT
    语句来检索 rowid
© www.soinside.com 2019 - 2024. All rights reserved.