Como faço para atualizar se existir, inserção se não (AKA “upsert” ou “merge”) no MySQL?

StackOverflow https://stackoverflow.com/questions/1218905

Pergunta

Existe uma maneira fácil de INSERT uma linha quando ela não existe, ou para UPDATE se existir, usando um MySQL consulta?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top