Eu recomendaria usar INSERT...ON DUPLICATE KEY UPDATE
.
Se você usar INSERT IGNORE
, a linha não será inserida se resultar em uma chave duplicada. Mas a declaração não gerará um erro. Em vez disso, gera um aviso. Esses casos incluem:
- inserir uma tecla duplicada nas colunas com
- Insira um nulo em uma coluna com uma restrição
NOT NULL
- Insira uma linha para uma tabela de partição, mas os valores que insere não são atribuídos a uma partição.
PRIMARY KEY
ou UNIQUE
Restrições.
Se você usar REPLACE
mysql realmente faz um DELETE
seguido por um INSERT
internamente, que tem alguns efeitos colaterais inesperados:
- Uma nova identificação auto-inclemente é atribuída.
- Linhas dependentes com chaves externas podem ser removidas (se as teclas externas em cascata forem usadas) ou evitar o
REPLACE
. - gatilhos que atiram no fogo sobre
DELETE
são executados desnecessariamente. - Os efeitos colaterais também são espalhados para os escravos da replicação íon.
Correção: ambos REPLACE
e são invenções não padrão, proprietários, específicos Mysql. ANSI SQL 2003 define um MERGE
que pode resolver a mesma necessidade (e mais), mas o MySQL não suporta a declaração MERGE
.
Um usuário tentou editar este post (a edição foi rejeitada pelos moderadores). A edição tentou adicionar uma afirmação que faz uma nova identificação auto-inclemente atribuída. É verdade que o novo ID é gerado, mas não é usado na linha alterada. Veja a demonstração abaixo, testada com o servidor permanentemente 5.5.28. A variável de configuração innodb_autoinc_lock_mode=1
(o valor padrão):
mysql> create table foo (id serial primary key, u int, unique key (u));mysql> insert into foo (u) values (10);mysql> select * from foo;+----+------+| id | u |+----+------+| 1 | 10 |+----+------+mysql> show create table foo\GCREATE TABLE `foo` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `u` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `u` (`u`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1mysql> insert into foo (u) values (10) on duplicate key update u = 20;mysql> select * from foo;+----+------+| id | u |+----+------+| 1 | 20 |+----+------+mysql> show create table foo\GCREATE TABLE `foo` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `u` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `u` (`u`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
O acima mostra que a declaração de Iodku detecta a duplicata e invoca a atualização para alterar o valor de u
. Observação O AUTO_INCREMENT=3
Indica que uma identificação foi gerada, mas não foi usada na linha.
enquanto REPLACE
Exclua a linha original e insira uma nova linha, gerando e armazenando uma nova identificação auto-inclusão:
mysql> select * from foo;+----+------+| id | u |+----+------+| 1 | 20 |+----+------+mysql> replace into foo (u) values (20);mysql> select * from foo;+----+------+| id | u |+----+------+| 3 | 20 |+----+------+