Как мне обновить, если существует, вставить, если нет (AKA «upsert» или «объединить») в MySQL?
-
10-07-2019 - |
Вопрос
Есть ли простой способ INSERT
строки, когда она не существует, или UPDATE
, если она существует, с помощью одного запроса MySQL?
Решение
Да, INSERT ... ON ОБНОВЛЕНИЕ КЛЮЧЕВЫХ КЛЮЧЕЙ
. Например:
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 правильно: есть < code> 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 строки, затронутые» в приведенном выше примере.) То есть он заменит значения всех столбцов существующей записи (а не просто обновит некоторые столбцы.) Поведение REPLACE INTO
в MySQL очень похоже на поведение INSERT OR REPLACE INTO
в Sqlite. Посмотрите этот вопрос для некоторых обходных путей, если вы хотите обновить только несколько столбцов ( и не все столбцы), если запись уже существует.