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