Jag skulle rekommendera att du använder INSERT...ON DUPLICATE KEY UPDATE
.
Om du använder INSERT IGNORE
, då kommer raden inte att infogas om den resulterar i en dubblettnyckel. Men uttalandet kommer inte att generera ett fel. Det genererar en varning istället. Dessa fall inkluderar:
- Infoga en dubblettnyckel i kolumner med
PRIMARY KEY
ellerUNIQUE
begränsningar. - Infoga en NULL i en kolumn med en
NOT NULL
begränsning. - Infoga en rad i en partitionerad tabell, men värdena du infogar mappas inte till en partition.
Om du använder REPLACE
, MySQL gör faktiskt en DELETE
följt av en INSERT
internt, vilket har några oväntade biverkningar:
- Ett nytt auto-inkrement-ID tilldelas.
- Beroende rader med främmande nycklar kan raderas (om du använder överlappande främmande nycklar) eller annars förhindrar
REPLACE
. - Triggers som aktiveras på
DELETE
körs i onödan. - Biverkningar sprids även till repliker.
korrigering: båda REPLACE
och INSERT...ON DUPLICATE KEY UPDATE
är icke-standardiserade, patentskyddade uppfinningar specifika för MySQL. ANSI SQL 2003 definierar en MERGE
uttalande som kan lösa samma behov (och mer), men MySQL stöder inte MERGE
uttalande.
En användare försökte redigera detta inlägg (redigeringen avvisades av moderatorer). Redigeringen försökte lägga till ett påstående som INSERT...ON DUPLICATE KEY UPDATE
gör att ett nytt auto-inkrement-id tilldelas. Det är sant att det nya ID:t är genererat , men den används inte i den ändrade raden.
Se demonstration nedan, testad med Percona Server 5.5.28. Konfigurationsvariabeln 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
Ovanstående visar att IODKU-satsen upptäcker dubbletten och anropar uppdateringen för att ändra värdet på u
. Notera AUTO_INCREMENT=3
indikerar att ett ID har genererats men inte använts i raden.
Medan REPLACE
tar bort den ursprungliga raden och infogar en ny rad, vilket genererar och lagra ett nytt auto-inkrement-id:
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 3 | 20 |
+----+------+