SQLite INSERT - ON DUPLICATE KEY UPDATE(UPSERT)

Ali*_*xel 92 mysql sql database sqlite upsert

MySQL有这样的东西:

INSERT INTO visits (ip, hits)
VALUES ('127.0.0.1', 1)
ON DUPLICATE KEY UPDATE hits = hits + 1;
Run Code Online (Sandbox Code Playgroud)

据我所知,SQLite中不存在此功能,我想知道的是,如果有任何方法可以实现相同的效果而无需执行两个查询.此外,如果无法做到这一点,您更喜欢什么:

  1. SELECT +(INSERT或UPDATE)
  2. 更新(如果UPDATE失败,则为 + INSERT )

dan*_*n04 115

INSERT OR IGNORE INTO visits VALUES ($ip, 0);
UPDATE visits SET hits = hits + 1 WHERE ip LIKE $ip;
Run Code Online (Sandbox Code Playgroud)

这要求"ip"列具有UNIQUE(或PRIMARY KEY)约束.


编辑:另一个很好的解决方案:https://stackoverflow.com/a/4330694/89771.

  • 只是为了记录,'REPLACE`不是一个选项. (2认同)

cod*_*lic 18

我更喜欢UPDATE (+ INSERT if UPDATE fails).更少的代码=更少的错误.


szm*_*618 14

从3.24.0开始,SQLite也支持upsert,所以现在你可以简单地编写以下内容

INSERT INTO visits (ip, hits)
VALUES ('127.0.0.1', 1)
ON CONFLICT(ip) DO UPDATE SET hits = hits + 1;
Run Code Online (Sandbox Code Playgroud)

  • 我想知道您是否可以在一个事务中执行多个这样的 `upsert`,即使用 Python 的 `executemany()` 函数? (3认同)
  • @jithu 您使用的是哪个版本的 SQLite? (2认同)

Jac*_*son 7

The current answer will only work in sqlite OR mysql (depending on if you use OR or not). So, if you want cross dbms compatibility, the following will do...

REPLACE INTO `visits` (ip, value) VALUES ($ip, 0);
Run Code Online (Sandbox Code Playgroud)

  • 接受的答案适用于SQLite(这是我的目标).`REPLACE`也适用于SQLite,但是在MySQL上它总会将计数器重置为0 - 而查询将是可移植的,最终结果会有很大不同. (3认同)