Mysql
 sql >> Datenbank >  >> RDS >> Mysql

INSERT IGNORE vs INSERT ... BEI DUPLICATE KEY UPDATE

Ich würde die Verwendung von INSERT...ON DUPLICATE KEY UPDATE empfehlen .

Wenn Sie INSERT IGNORE verwenden , dann wird die Zeile nicht wirklich eingefügt, wenn sie zu einem doppelten Schlüssel führt. Aber die Anweisung erzeugt keinen Fehler. Stattdessen wird eine Warnung generiert. Zu diesen Fällen gehören:

  • Einfügen eines doppelten Schlüssels in Spalten mit PRIMARY KEY oder UNIQUE Einschränkungen.
  • Einfügen einer NULL in eine Spalte mit einem NOT NULL Einschränkung.
  • Einfügen einer Zeile in eine partitionierte Tabelle, aber die eingefügten Werte werden keiner Partition zugeordnet.

Wenn Sie REPLACE verwenden , führt MySQL tatsächlich ein DELETE durch gefolgt von einem INSERT intern, was einige unerwartete Nebeneffekte hat:

  • Eine neue Auto-Increment-ID wird zugewiesen.
  • Abhängige Zeilen mit Fremdschlüsseln können gelöscht werden (wenn Sie kaskadierende Fremdschlüssel verwenden) oder sonst das REPLACE verhindern .
  • Trigger, die bei DELETE ausgelöst werden werden unnötigerweise ausgeführt.
  • Nebenwirkungen werden auch auf Replikate übertragen.

Korrektur: beide REPLACE und INSERT...ON DUPLICATE KEY UPDATE sind nicht standardmäßige, proprietäre Erfindungen, die für MySQL spezifisch sind. ANSI SQL 2003 definiert ein MERGE -Anweisung, die denselben Bedarf (und mehr) lösen kann, aber MySQL unterstützt nicht MERGE Aussage.

Ein Benutzer hat versucht, diesen Beitrag zu bearbeiten (die Bearbeitung wurde von Moderatoren abgelehnt). Die Bearbeitung hat versucht, eine Behauptung hinzuzufügen, dass INSERT...ON DUPLICATE KEY UPDATE bewirkt, dass eine neue Auto-Increment-ID zugewiesen wird. Es stimmt, dass die neue ID erzeugt wird , wird aber in der geänderten Zeile nicht verwendet.

Siehe Demonstration unten, getestet mit Percona Server 5.5.28. Die Konfigurationsvariable 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

Das Obige zeigt, dass die IODKU-Anweisung das Duplikat erkennt und die Aktualisierung aufruft, um den Wert von u zu ändern . Beachten Sie das AUTO_INCREMENT=3 gibt an, dass eine ID generiert, aber in der Zeile nicht verwendet wurde.

Während REPLACE löscht die ursprüngliche Zeile und fügt eine neue Zeile ein, wodurch und erzeugt werden Speichern einer neuen 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 |
+----+------+