关于sql:如果存在则如何更新,如果不是,则插入(AKA“upsert”或“merge”)在MySQL中?

How do I update if exists, insert if not (AKA “upsert” or “merge”) in MySQL?

是否有一个简单的方法INSERT一行不存在时,或UPDATE如果它存在,使用一个MySQL查询?


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

1
2
3
4
5
6
INSERT INTO `usage`
(`thing_id`, `times_used`, `first_time_used`)
VALUES
(4815162342, 1, NOW())
ON DUPLICATE KEY UPDATE
`times_used` = `times_used` + 1


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

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

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

REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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。如果您只想更新一些列(而不是所有列),如果该记录已存在,请参阅此问题以获取一些解决方法。