Je recommanderais d'utiliser INSERT...ON DUPLICATE KEY UPDATE
.
Si vous utilisez INSERT IGNORE
, la ligne ne sera pas réellement insérée si elle aboutit à une clé en double. Mais l'instruction ne générera pas d'erreur. Il génère un avertissement à la place. Ces cas incluent :
- Insérer une clé en double dans les colonnes avec
PRIMARY KEY
ouUNIQUE
contraintes. - Insérer un NULL dans une colonne avec un
NOT NULL
contrainte. - Insérer une ligne dans une table partitionnée, mais les valeurs que vous insérez ne correspondent pas à une partition.
Si vous utilisez REPLACE
, MySQL fait en fait un DELETE
suivi d'un INSERT
en interne, ce qui a des effets secondaires inattendus :
- Un nouvel ID d'incrémentation automatique est attribué.
- Les lignes dépendantes avec des clés étrangères peuvent être supprimées (si vous utilisez des clés étrangères en cascade) ou bien empêcher le
REPLACE
. - Déclencheurs qui se déclenchent sur
DELETE
sont exécutés inutilement. - Les effets secondaires se propagent également aux répliques.
corrigé : les deux REPLACE
et INSERT...ON DUPLICATE KEY UPDATE
sont des inventions propriétaires non standard spécifiques à MySQL. ANSI SQL 2003 définit un MERGE
déclaration qui peut résoudre le même besoin (et plus), mais MySQL ne prend pas en charge le MERGE
déclaration.
Un utilisateur a essayé de modifier ce message (la modification a été rejetée par les modérateurs). La modification a tenté d'ajouter une revendication qui INSERT...ON DUPLICATE KEY UPDATE
provoque l'attribution d'un nouvel identifiant d'auto-incrémentation. Il est vrai que le nouvel identifiant est généré , mais il n'est pas utilisé dans la ligne modifiée.
Voir la démonstration ci-dessous, testée avec Percona Server 5.5.28. La variable de configuration innodb_autoinc_lock_mode=1
(valeur par défaut) :
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\G
CREATE 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=latin1
mysql> 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\G
CREATE 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
Ce qui précède montre que l'instruction IODKU détecte le doublon et appelle la mise à jour pour modifier la valeur de u
. Notez le AUTO_INCREMENT=3
indique qu'un identifiant a été généré, mais pas utilisé dans la ligne.
Alors que REPLACE
supprime la ligne d'origine et insère une nouvelle ligne, générant et stocker un nouvel identifiant d'incrémentation automatique :
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 3 | 20 |
+----+------+