Как мне обновить, если существует, вставить, если нет (AKA "upsert" или "объединить") в MySQL?

Есть ли простой способ INSERT строка, когда она не существует, или UPDATE если он существует, используя один запрос MySQL?

2 ответа

Решение

Да, 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

Я знаю, что это старый вопрос, но 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's INSERT OR REPLACE INTO, Посмотрите этот вопрос для некоторых обходных путей, если вы хотите обновить только несколько столбцов (и не все столбцы), если запись уже существует.

Другие вопросы по тегам