sql >> Database teknologi >  >> RDS >> Mysql

INSERT IGNORE vs INSERT ... PÅ DUBLIKAT NØGLOPDATERING

Jeg vil anbefale at bruge INSERT...ON DUPLICATE KEY UPDATE .

Hvis du bruger INSERT IGNORE , så vil rækken faktisk ikke blive indsat, hvis det resulterer i en dubletnøgle. Men erklæringen genererer ikke en fejl. Det genererer i stedet en advarsel. Disse tilfælde omfatter:

  • Indsættelse af en dubletnøgle i kolonner med PRIMARY KEY eller UNIQUE begrænsninger.
  • Indsættelse af en NULL i en kolonne med en NOT NULL begrænsning.
  • Indsættelse af en række i en partitioneret tabel, men de værdier, du indsætter, er ikke knyttet til en partition.

Hvis du bruger REPLACE , MySQL laver faktisk en DELETE efterfulgt af en INSERT internt, hvilket har nogle uventede bivirkninger:

  • Et nyt auto-increment ID er tildelt.
  • Afhængige rækker med fremmednøgler kan blive slettet (hvis du bruger cascading fremmednøgler) eller forhindre REPLACE .
  • Triggere, der udløses på DELETE udføres unødigt.
  • Bivirkninger forplantes også til replikaer.

rettelse: begge REPLACE og INSERT...ON DUPLICATE KEY UPDATE er ikke-standardiserede, proprietære opfindelser, der er specifikke for MySQL. ANSI SQL 2003 definerer en MERGE sætning, der kan løse det samme behov (og mere), men MySQL understøtter ikke MERGE erklæring.

En bruger forsøgte at redigere dette indlæg (redigeringen blev afvist af moderatorer). Redigeringen forsøgte at tilføje et krav, der INSERT...ON DUPLICATE KEY UPDATE forårsager, at et nyt auto-increment-id tildeles. Det er rigtigt, at det nye id er genereret , men den bruges ikke i den ændrede række.

Se demonstration nedenfor, testet med Percona Server 5.5.28. Konfigurationsvariablen innodb_autoinc_lock_mode=1 (standard):

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

Ovenstående viser, at IODKU-sætningen registrerer duplikatet og kalder opdateringen for at ændre værdien af ​​u . Bemærk AUTO_INCREMENT=3 angiver, at et id blev genereret, men ikke brugt i rækken.

Mens REPLACE sletter den originale række og indsætter en ny række, hvilket genererer og gemmer et nyt auto-increment id:

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


  1. Webinar:Nye funktioner i PostgreSQL 11 [Opfølgning]

  2. Forstå Workload Analyzer til at kortlægge ydeevneflaskehalse

  3. Fix:"BACKUP LOG kan ikke udføres, fordi der ikke er nogen aktuel database backup." i SQL Server/SQL Edge

  4. masseindsæt fra Java til Oracle