Como faço para atualizar se existir, inserção se não (AKA “upsert” ou “merge”) no MySQL?
-
10-07-2019 - |
Pergunta
Existe uma maneira fácil de INSERT
uma linha quando ela não existe, ou para UPDATE
se existir, usando um MySQL consulta?
Solução
Sim, INSERT ... ON DUPLICATE KEY UPDATE
. Por exemplo:
INSERT INTO `usage`
(`thing_id`, `times_used`, `first_time_used`)
VALUES
(4815162342, 1, NOW())
ON DUPLICATE KEY UPDATE
`times_used` = `times_used` + 1
Outras dicas
Eu sei que isto é uma questão de idade, mas o Google me levar aqui recentemente então eu imagino outros vêm também.
@chaos está correto: há a INSERT ... ON DUPLICATE KEY UPDATE
sintaxe.
No entanto, a pergunta original perguntado sobre MySQL especificamente, e em MySQL existe a REPLACE INTO ...
sintaxe. IMHO, este comando é mais fácil e simples de usar para upserts. A partir do manual:
REPLACE funciona exatamente como INSERT, exceto que se um velho linha na tabela tem o mesmo valor que uma nova linha para uma chave primária ou um índice exclusivo, a velha linha é excluída antes da nova linha é inserida.
Note que este não é o padrão SQL. Um exemplo do manual:
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)
Editar: Apenas um aviso justo que REPLACE INTO
não é como UPDATE
. Como diz o manual, REPLACE
exclui a linha se existir, em seguida, insere um novo. (Observe os engraçados "2 linhas afetadas" no exemplo acima.) Ou seja, ele irá substituir os valores de todas colunas de um registro existente (e não meramente update alguns colunas.) O comportamento do REPLACE INTO
do MySQL é muito semelhante ao de INSERT OR REPLACE INTO
do SQLite. Consulte esta questão para algumas soluções alternativas, se você só quer atualizar algumas colunas ( e não todas as colunas) se o registro já existe.