sql >> Database >  >> RDS >> Mysql

INSERT IGNORE vs INSERT ... OP DUPLICATE KEY UPDATE

Ik zou aanraden om INSERT...ON DUPLICATE KEY UPDATE te gebruiken .

Als u INSERT IGNORE . gebruikt , dan wordt de rij niet daadwerkelijk ingevoegd als dit resulteert in een dubbele sleutel. Maar de instructie genereert geen fout. Het genereert in plaats daarvan een waarschuwing. Deze gevallen omvatten:

  • Een dubbele sleutel invoegen in kolommen met PRIMARY KEY of UNIQUE beperkingen.
  • Een NULL invoegen in een kolom met een NOT NULL beperking.
  • Een rij invoegen in een gepartitioneerde tabel, maar de waarden die u invoegt, worden niet toegewezen aan een partitie.

Als u REPLACE . gebruikt , MySQL doet eigenlijk een DELETE gevolgd door een INSERT intern, wat enkele onverwachte bijwerkingen heeft:

  • Er wordt een nieuwe auto-increment ID toegewezen.
  • Afhankelijke rijen met externe sleutels kunnen worden verwijderd (als u trapsgewijze externe sleutels gebruikt) of anders voorkomen dat de REPLACE .
  • Triggers die vuren op DELETE worden onnodig uitgevoerd.
  • Bijwerkingen worden ook doorgegeven aan replica's.

correctie: beide REPLACE en INSERT...ON DUPLICATE KEY UPDATE zijn niet-standaard, gepatenteerde uitvindingen die specifiek zijn voor MySQL. ANSI SQL 2003 definieert een MERGE verklaring die dezelfde behoefte (en meer) kan oplossen, maar MySQL ondersteunt de MERGE niet verklaring.

Een gebruiker heeft geprobeerd dit bericht te bewerken (de bewerking is afgewezen door moderators). De bewerking heeft geprobeerd een claim toe te voegen dat INSERT...ON DUPLICATE KEY UPDATE zorgt ervoor dat een nieuwe auto-increment id wordt toegewezen. Het is waar dat de nieuwe id is gegenereerd , maar het wordt niet gebruikt in de gewijzigde rij.

Zie onderstaande demonstratie, getest met Percona Server 5.5.28. De configuratievariabele innodb_autoinc_lock_mode=1 (de standaardinstelling):

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

Het bovenstaande toont aan dat de IODKU-instructie het duplicaat detecteert en de update aanroept om de waarde van u te wijzigen . Let op de AUTO_INCREMENT=3 geeft aan dat een id is gegenereerd, maar niet in de rij is gebruikt.

Terwijl REPLACE verwijdert de originele rij en voegt een nieuwe rij in, waarbij en . worden gegenereerd een nieuwe auto-increment-id opslaan:

mysql> select * from foo;
+----+------+
| id | u    |
+----+------+
|  1 |   20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u    |
+----+------+
|  3 |   20 |
+----+------+


  1. AVG ophalen waarbij nul- of nulwaarden worden genegeerd

  2. Twee rijen samenvoegen tot één terwijl u null-waarden vervangt

  3. Entity Framework en meerdere schema's

  4. Verwijder duplicaten uit Count() Resultaten in SQLite