如果存在我如何更新,如果不插入(即“ upsert”或“合并”)在 MySQL?

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

63092 次浏览

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

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

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

然而,最初的问题是关于 MySQL 的,在 MySQL 中有 REPLACE INTO ...语法。恕我直言,这个命令对于 upserts 来说更简单、更直接。手册上说:

REPLACE 的工作方式与 INSERT 完全相同,只是如果表中的旧行与 PRIMARYKEY 或 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非常相似。如果只想在记录已经存在的情况下更新少数几个列(而不是所有列) ,请参阅 这个问题了解一些解决方案。