如果存在,如何更新,如果没有(AKA"upsert"或"merge")在MySQL中插入?

blu*_*lub 150 mysql sql upsert insert-update

使用一个MySQL查询时,是否存在一种简单的方法,INSERT当它不存在时,或者UPDATE它是否存在?

cha*_*aos 189

是的,INSERT ... ON DUPLICATE KEY UPDATE.例如:

INSERT INTO `usage`
(`thing_id`, `times_used`, `first_time_used`)
VALUES
(4815162342, 1, NOW())
ON DUPLICATE KEY UPDATE
`times_used` = `times_used` + 1
Run Code Online (Sandbox Code Playgroud)

  • 是的,我相信SQL Server的等价物称为"MERGE".一般来说,这个概念通常被称为"UPSERT". (10认同)
  • @blub:如果你在`geb`和`topic`上创建一个唯一键,它将起作用(`ALTER TABLE表ADD UNIQUE geb_by_topic(geb,topic)`). (3认同)
  • 谢谢,你可以使用`VALUES(col)`来获取insert参数的值,以防重复.例如:`ON DUPLICATE UPDATE b = VALUES(b),c = VALUES(c)` (3认同)

Arm*_*Jim 6

我知道这是一个老问题,但最近谷歌把我带到了这里,所以我想其他人也会来这里。

@chaos 是正确的:有INSERT ... ON DUPLICATE KEY UPDATE语法。

但是,最初的问题专门询问了 MySQL,在 MySQL 中有REPLACE INTO ...语法。恕我直言,这个命令用于 upserts 更容易、更直接。从手册:

REPLACE 的工作方式与 INSERT 完全相同,但如果表中的旧行与 PRIMARY KEY 或 UNIQUE 索引的新行具有相同的值,则在插入新行之前删除旧行。

请注意,这不是标准 SQL。手册中的一个例子:

CREATE TABLE test (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  data VARCHAR(64) DEFAULT NULL,
  ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
);

mysql> REPLACE INTO test VALUES (1, 'Old', '2014-08-20 18:47:00');
Query OK, 1 row affected (0.04 sec)

mysql> REPLACE INTO test VALUES (1, 'New', '2014-08-20 18:47:42');
Query OK, 2 rows affected (0.04 sec)

mysql> SELECT * FROM test;
+----+------+---------------------+
| id | data | ts                  |
+----+------+---------------------+
|  1 | New  | 2014-08-20 18:47:42 |
+----+------+---------------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

编辑:只是一个公平的警告,REPLACE INTO不像UPDATE. 正如手册所说,REPLACE如果该行存在,则删除该行,然后插入一个新行。(注意上面示例中有趣的“受影响的 2 行”。)也就是说,它将替换现有记录的所有列的值(而不仅仅是更新某些列。)MySQL 的行为REPLACE INTO与 Sqlite 的INSERT OR REPLACE INTO. 如果您只想在记录已存在的情况下更新几列(而不是所有列),请参阅此问题以了解一些解决方法。