SQLite插入-重复键更新(UPSERT)


98

MySQL有这样的东西:

INSERT INTO visits (ip, hits)
VALUES ('127.0.0.1', 1)
ON DUPLICATE KEY UPDATE hits = hits + 1;

据我所知,SQLite中不存在此功能,我想知道的是,是否有任何方法可以实现相同的效果而不必执行两个查询。另外,如果这不可能,那么您更喜欢什么:

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

Answers:


31

因为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;

3
我想知道您是否可以upsert在一个事务中(例如使用Python executemany()函数)执行多个这样的操作?
无线电控制的



7

当前答案仅在sqlite OR mysql中有效(取决于您是否使用OR)。因此,如果您希望跨dbms兼容性,则可以执行以下操作:

REPLACE INTO `visits` (ip, value) VALUES ($ip, 0);

3
可接受的答案适用于SQLite(这是我的目标)。REPLACE也可以在SQLite上使用,但是在MySQL上,它将始终将计数器重置为0-尽管查询是可移植的,但最终结果会相差很多。
Alix Axel 2012年

没错,我以为OP正在寻找可移植的东西。我知道REPLACE INTO不能在所有情况下都可以使用,尤其是在需要保存PK的情况下,但在很多情况下都可以。
Jacob Thomason

完全失败而不是丢弃数据是一项功能,而不是错误。
东武

-4

您应该为此使用memcached,因为它是存储单个值(访问次数)的单个键(IP地址)。您可以使用原子增量功能来确保没有“竞赛”条件。

它比MySQL更快,并且节省了负载,因此MySQL可以专注于其他事情。


如果数据不是那么重要,那就可以。但是,如果在繁忙站点上使用该IP,许多IP都在访问该服务,则memcached实例可能已满,并导致某些内容被丢弃。备份memcached的内容也将是有趣的(如果需要)
埃利奥特福斯特

@ElliotFoster Memcached可以处理与您向其抛出的RAM一样多的数据(如果需要持久性,还可以使用redis或membase)。如果您每天有超过一百万的访问者,那么您可能可以负担得起为您的memcache实例提供超过30MB的ram(我认为这是默认值)。但是,就您提供的内存量而言,它肯定可以处理比SQLite和MySQL高得多的负载-根本没有任何比较。
Xeoncross 2011年

请不要将我的评论误认为是反对内存缓存的投票,因为我认为这是一个了不起的工具。就像redis一样(我没有用过它,所以我不能代表membase。)但是,memcache / redis并不是最可靠的存储。是的,redis具有持久性,但是数据以一定间隔(最后一次我看过)持久存储到磁盘,而memcache则根本没有。就像我说的那样,如果数据不重要(或可以轻松重现),那么内存缓存和公司将非常出色。最初的帖子还询问sqlite,它与MySQL有很大的不同,可能意味着它们在其他方面受到限制。
艾略特·福斯特

您可以配置Redis以所需的速度持久存储数据(X秒钟或Y更改次数)。
布法罗2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.