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