Mysql
 sql >> Base de données >  >> RDS >> Mysql

INSERT IGNORE vs INSERT ... ON DUPLICATE KEY UPDATE

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 ou UNIQUE 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 |
+----+------+