如何在MySQL中更新是否存在(如果存在),如果不存在则插入(又称为“ upsert”或“ merge”)?


152

有没有一种简单的方法可以使用一个MySQL查询INSERT对不存在的行或存在的行进行简单的处理UPDATE

Answers:


191

使用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

10
是的,我相信SQL Server的等效项称为MERGE。通常,该概念通常称为"UPSERT"
混乱

3
@blub:如果您在上创建一个唯一键gebtopic它将起作用(ALTER TABLE table ADD UNIQUE geb_by_topic (geb, topic))。
混乱

1
@Brian:也称为Oracle的等效项,MERGE但我不确定其语法是否与SQL Server的语法相同。
Ken Keenan

1
@Brooks:如果将其传递为0,则它​​将实际上使用0作为值。所以不要那样做。不要将其传递给任何东西,也不要传递给它NULL以使auto_increment行为起作用(否则,是的,可以按照您的假设进行工作;请参见dev.mysql.com/doc/refman/5.5/en/example-auto-increment。 html)。
2012年

3
谢谢,VALUES(col)如果有重复,您可以用来从insert参数获取值。例如:ON DUPLICATE UPDATE b = VALUES(b), c = VALUES(c)
gerrytan

5

我知道这是一个老问题,但是Google最近将我引到了这里,所以我想其他人也会来这里。

@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)

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

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.