sql >> Databasteknik >  >> RDS >> Mysql

INSERT IGNORE vs INSERT ... PÅ DUBLIKATNYCKELUPPDATERING

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 eller UNIQUE 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 |
+----+------+


  1. TIMESTAMPADD() Exempel – MySQL

  2. Introduktion till PL/SQL-undantagshantering i Oracle Database

  3. HA för MySQL och MariaDB - Jämför Master-Master-replikering med Galera Cluster

  4. Kan jag kopiera en rad i MySQL för att infoga i samma tabell?