Ich würde empfehlen, zu verwenden INSERT...ON DUPLICATE KEY UPDATE
.
Wenn Sie verwenden INSERT IGNORE
, wird die Zeile nicht wirklich eingefügt, wenn dies zu einem doppelten Schlüssel führt. Die Anweisung generiert jedoch keinen Fehler. Stattdessen wird eine Warnung generiert. Diese Fälle umfassen:
- Einfügen eines doppelten Schlüssels in Spalten mit
PRIMARY KEY
oder UNIQUE
Einschränkungen.
- Einfügen eines NULL in eine Spalte mit einer
NOT NULL
Einschränkung.
- Einfügen einer Zeile in eine partitionierte Tabelle, aber die Werte, die Sie einfügen, werden keiner Partition zugeordnet.
Wenn Sie verwenden REPLACE
, führt MySQL tatsächlich DELETE
ein INSERT
internes gefolgt von einem durch , was einige unerwartete Nebenwirkungen hat:
- Eine neue Auto-Inkrement-ID wird zugewiesen.
- Abhängige Zeilen mit Fremdschlüsseln können gelöscht werden (wenn Sie kaskadierende Fremdschlüssel verwenden) oder das verhindern
REPLACE
.
- Auslöser, die ausgelöst werden,
DELETE
werden unnötig ausgeführt.
- Nebenwirkungen werden auch auf Replikate übertragen.
Korrektur: beides REPLACE
und INSERT...ON DUPLICATE KEY UPDATE
nicht standardmäßige, proprietäre Erfindungen, die für MySQL spezifisch sind. ANSI SQL 2003 definiert eine MERGE
Anweisung, die denselben Bedarf (und mehr) lösen kann, aber MySQL unterstützt die MERGE
Anweisung nicht.
Ein Benutzer hat versucht, diesen Beitrag zu bearbeiten (die Bearbeitung wurde von den Moderatoren abgelehnt). Bei der Bearbeitung wurde versucht, einen Anspruch hinzuzufügen, der INSERT...ON DUPLICATE KEY UPDATE
bewirkt , dass eine neue ID für die automatische Inkrementierung zugewiesen wird. Es ist wahr, dass die neue ID generiert wird , aber sie wird nicht in der geänderten Zeile verwendet.
Siehe unten stehende Demonstration, getestet mit Percona Server 5.5.28. Die Konfigurationsvariable innodb_autoinc_lock_mode=1
(Standardeinstellung):
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 zu ändern u
. Beachten Sie, AUTO_INCREMENT=3
dass eine ID generiert, aber nicht in der Zeile verwendet wurde.
Während REPLACE
die ursprüngliche Zeile gelöscht und eine neue Zeile eingefügt wird, wird eine neue Auto-Inkrement-ID generiert und gespeichert:
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 3 | 20 |
+----+------+
INSERT ... ON DUPLICATE KEY UPDATE ...
Aussagen gefüllt ist. Viele der Daten sind doppelt vorhanden, und es hat dazu geführt, dass eine Instanz der AI-PK zwischen zwei Zeilen von 17.029.941 auf 46.271.740 gestiegen ist. Diese Generation einer neuen KI bedeutet jedes Mal, dass Ihre Reichweite sehr schnell gefüllt werden kann und Sie aufräumen müssen. Dieser Tisch ist erst zwei Wochen alt!Wenn Sie sehen möchten, was dies alles bedeutet, finden Sie hier einen Überblick über alles:
Der Primärschlüssel basiert auf beiden Spalten dieser Kurzreferenztabelle. Ein Primärschlüssel erfordert eindeutige Werte.
Lass uns anfangen:
Beachten Sie, dass durch das oben Gesagte zu viel zusätzliche Arbeit gespart wurde, indem die Spalte auf sich selbst gesetzt wurde. Es ist kein Update erforderlich
und jetzt einige mehrzeilige Tests:
In der Konsole wurden keine anderen Nachrichten generiert, und diese 4 Werte sind jetzt in den Tabellendaten enthalten. Ich habe alles außer (1,1) gelöscht, damit ich vom selben Spielfeld aus testen konnte
Da haben Sie es also. Da dies alles an einem frischen Tisch ohne Daten und ohne Produktion durchgeführt wurde, waren die Ausführungszeiten mikroskopisch und irrelevant. Jeder mit realen Daten wäre herzlich eingeladen, diese beizutragen.
quelle
INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
.Etwas Wichtiges hinzuzufügen: Wenn Sie INSERT IGNORE verwenden und Sie Schlüsselverletzungen haben, gibt MySQL KEINE Warnung aus!
Wenn Sie beispielsweise versuchen, 100 Datensätze gleichzeitig einzufügen, wobei einer fehlerhaft ist, gelangen Sie in den interaktiven Modus:
Wie Sie sehen: Keine Warnungen! Dieses Verhalten ist in der offiziellen MySQL-Dokumentation sogar falsch beschrieben.
Wenn Ihr Skript informiert werden muss und einige Datensätze nicht hinzugefügt wurden (aufgrund von Schlüsselverletzungen), müssen Sie mysql_info () aufrufen und es auf den Wert "Duplikate" analysieren.
quelle
mysqli_affected_rows()
wissen, ob dasINSERT
tatsächlich passiert ist.Cannot add or update a child row: a foreign key constraint fails
und keine Zeilen (auch gültig ist) hinzugefügt werden .INSERT IGNORE
werden doppelte Schlüssel ohne Fehler oder Warnung ignoriert.Ich benutze
INSERT IGNORE
es routinemäßig und es klingt genau so, wie Sie es auch suchen. Solange Sie wissen, dass Zeilen, die Indexkonflikte verursachen würden, nicht eingefügt werden und Sie Ihr Programm entsprechend planen, sollte dies keine Probleme verursachen.quelle
Ich weiß, dass dies alt ist, aber ich werde diesen Hinweis hinzufügen, falls jemand anderes (wie ich) auf diese Seite gelangt, während er versucht, Informationen zu INSERT..IGNORE zu finden.
Wie oben erwähnt, werden bei Verwendung von INSERT..IGNORE Fehler, die beim Ausführen der INSERT-Anweisung auftreten, stattdessen als Warnungen behandelt.
Eine Sache, die nicht explizit erwähnt wird, ist, dass INSERT..IGNORE dazu führt, dass ungültige Werte beim Einfügen auf die nächsten Werte angepasst werden (während ungültige Werte dazu führen würden, dass die Abfrage abgebrochen wird, wenn das Schlüsselwort IGNORE nicht verwendet wird).
quelle
ON DUPLICATE KEY UPDATE ist nicht wirklich im Standard. Es ist ungefähr so Standard wie REPLACE. Siehe SQL MERGE .
Im Wesentlichen sind beide Befehle Versionen mit alternativer Syntax von Standardbefehlen.
quelle
Replace
Into scheint eine Option zu sein. Oder Sie können mit überprüfenDies wird eingefügt oder gelöscht und dann eingefügt. Ich neige dazu, zuerst einen
IF NOT EXISTS
Scheck zu machen.quelle
REPLACE
in der Tabelle löscht alle Zeilen mit passendem beliebigenPRIMARY
oderUNIQUE
Schlüssel, dannINSERTs
. Dies ist möglicherweise viel mehr Arbeit als IODKU.Mögliche Gefahr von INSERT IGNORE. Wenn Sie versuchen, einen VARCHAR-Wert länger als die Spalte einzufügen, wurde die Spalte mit definiert - der Wert wird abgeschnitten und eingefügt, AUCH WENN der strikte Modus aktiviert ist.
quelle
Wenn Sie
insert ignore
eineSHOW WARNINGS;
Anweisung am Ende Ihres Abfragesatzes verwenden, wird eine Tabelle mit allen Warnungen angezeigt, einschließlich der IDs, die die Duplikate waren.quelle
SHOW WARNINGS;
scheint nur die letzte Abfrage zu beeinflussen. Alle vorherigen Anweisungen werden nicht akkumuliert, wenn Sie mehr als eine einzelne Anweisung haben.Wenn Sie in die Tabelle und in den Konflikt des Primärschlüssels oder des eindeutigen Index einfügen möchten, wird die widersprüchliche Zeile aktualisiert, anstatt diese Zeile einzufügen.
Syntax:
Hier sieht diese Einfügeanweisung möglicherweise anders aus als zuvor. Diese Einfügeanweisung versucht, eine Zeile in Tabelle1 mit dem Wert a und b in Spalte Spalte1 bzw. Spalte2 einzufügen.
Lassen Sie uns diese Aussage im Detail verstehen:
Beispiel: Hier ist Spalte1 als Primärschlüssel in Tabelle1 definiert.
Wenn es in Tabelle 1 keine Zeile mit dem Wert "a" in Spalte 1 gibt. Diese Anweisung fügt also eine Zeile in die Tabelle1 ein.
Wenn sich nun in Tabelle 1 eine Zeile mit dem Wert "a" in Spalte 2 befindet. Diese Anweisung aktualisiert also den Wert für Spalte2 der Zeile mit "c", wobei der Wert für Spalte1 "a" ist.
Wenn Sie also eine neue Zeile einfügen möchten, aktualisieren Sie diese Zeile andernfalls im Konflikt mit dem Primärschlüssel oder dem eindeutigen Index.
Lesen Sie mehr unter diesem Link
quelle
INSERT...ON DUPLICATE KEY UPDATE
wird bevorzugt, um die Verwaltung unerwarteter Ausnahmen zu verhindern.Diese Lösung funktioniert nur, wenn Sie ** 1 eindeutige Einschränkung ** haben
In meinem Fall weiß ich das
col1
undcol2
erstelle einen eindeutigen zusammengesetzten Index.Es verfolgt den Fehler, löst jedoch keine Ausnahme beim Duplizieren aus. In Bezug auf die Leistung ist das Update mit demselben Wert effizient, da MySQL dies bemerkt und nicht aktualisiert
Die Idee, diesen Ansatz zu verwenden, kam aus den Kommentaren unter phpdelusions.net/pdo .
quelle