SQLite - UPSERT *不是* INSERT 或 REPLACE

标签 sql sqlite upsert

http://en.wikipedia.org/wiki/Upsert

Insert Update stored proc on SQL Server

在 SQLite 中是否有一些我没有想到的聪明的方法来做到这一点?

基本上,如果记录存在,我想更新四列中的三列, 如果它不存在,我想用第四列的默认值 (NUL) 插入记录。

ID 是主键,因此 UPSERT 永远只有一条记录。

(我试图避免 SELECT 的开销,以便确定我是否需要更新或显然插入)

建议?


我无法在 SQLite 站点上确认 TABLE CREATE 的语法。 我没有构建演示来测试它,但它似乎不受支持。

如果是,我有三列,所以它实际上看起来像:

CREATE TABLE table1( 
    id INTEGER PRIMARY KEY ON CONFLICT REPLACE, 
    Blob1 BLOB ON CONFLICT REPLACE, 
    Blob2 BLOB ON CONFLICT REPLACE, 
    Blob3 BLOB 
);

但前两个 blob 不会导致冲突,只有 ID 会 所以我假设 Blob1 和 Blob2 不会被替换(根据需要)


当绑定(bind)数据是一个完整的事务时,SQLite 中的更新,意思是 每个要更新的发送行都需要:Prepare/Bind/Step/Finalize 语句 与允许使用重置功能的 INSERT 不同

语句对象的生命周期是这样的:

  1. 使用 sqlite3_prepare_v2() 创建对象
  2. 使用 sqlite3_bind_ 接口(interface)将值绑定(bind)到主机参数。
  3. 通过调用 sqlite3_step() 运行 SQL
  4. 使用 sqlite3_reset() 重置语句,然后返回步骤 2 并重复。
  5. 使用 sqlite3_finalize() 销毁语句对象。

我猜 UPDATE 与 INSERT 相比速度较慢,但​​它与使用主键的 SELECT 相比如何?

也许我应该使用 select 读取第 4 列 (Blob3),然后使用 REPLACE 写入新记录,将原始第 4 列与前 3 列的新数据混合?

最佳答案

假设表中有三列:ID、NAME、ROLE


错误:这将为 ID=1 插入或替换所有列的新值:

INSERT OR REPLACE INTO Employee (id, name, role) 
  VALUES (1, 'John Foo', 'CEO');

错误:这将插入或替换 2 列...NAME 列将设置为 NULL 或默认值:

INSERT OR REPLACE INTO Employee (id, role) 
  VALUES (1, 'code monkey');

GOOD:使用 SQLite On conflict 子句 UPSERT support in SQLite! UPSERT 语法已添加到 SQLite 3.24.0 版!

UPSERT 是对 INSERT 的一种特殊语法添加,如果 INSERT 违反唯一性约束,它会导致 INSERT 表现为 UPDATE 或空操作。 UPSERT 不是标准 SQL。 SQLite 中的 UPSERT 遵循 PostgreSQL 建立的语法。

enter image description here

好但乏味:这将更新其中的 2 个列。 当 ID=1 存在时,NAME 不受影响。 当ID=1不存在时,名称将是默认的(NULL)。

INSERT OR REPLACE INTO Employee (id, role, name) 
  VALUES (  1, 
            'code monkey',
            (SELECT name FROM Employee WHERE id = 1)
          );

这将更新其中的 2 列。 当ID=1存在时,ROLE不受影响。 当 ID=1 不存在时,角色将被设置为 'Benchwarmer' 而不是默认值。

INSERT OR REPLACE INTO Employee (id, name, role) 
  VALUES (  1, 
            'Susan Bar',
            COALESCE((SELECT role FROM Employee WHERE id = 1), 'Benchwarmer')
          );

关于SQLite - UPSERT *不是* INSERT 或 REPLACE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/418898/

相关文章:

php - 拉维尔 4 : prevent lazy load hasMany relation when foreign_key is null (optional relation)

sql - 优化我的 mysql 查询以使用索引进行排序

mysql - 获取mysql中某个值出现的百分比

sql - SQL 子查询中的局部变量赋值

sqlite - 如何将 rowid 列变成常规列?

sql - 使用 SQL 计算 AVG,限制为最后 10 行并按 SQLite 中的字段分组

mysql - 插入 MySQL 表或更新(如果存在)

mysql - sql通过列号/索引/位置而不是列名选择列

mongodb - 是否可以使用 $inc 通过 Mongoose 更新子文档?

c# - TSQL 大量插入关系数据,带外键 Upsert