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
ellerUNIQUE
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 |
+----+------+