statement - mysql update




"INSERT IGNORE" vs "INSERT... ON DUPLICATE KEY UPDATE" (7)

Etwas Wichtiges zum Hinzufügen: Wenn INSERT IGNORE verwendet wird und Sie Schlüsselverletzungen haben, löst MySQL KEINE Warnung aus!

Wenn Sie beispielsweise versuchen, jeweils 100 Datensätze mit einem fehlerhaften Datensatz einzufügen, gelangen Sie in den interaktiven Modus:

Query OK, 99 rows affected (0.04 sec)

Records: 100 Duplicates: 1 Warnings: 0

Wie Sie sehen: Keine Warnungen! Dieses Verhalten wird in der offiziellen Mysql-Dokumentation sogar falsch beschrieben.

Wenn Ihr Skript informiert werden muss, wenn einige Datensätze nicht hinzugefügt wurden (aufgrund von Schlüsselverletzungen), müssen Sie mysql_info () aufrufen und für den Wert "Duplicates" analysieren.

Beim Ausführen einer INSERT Anweisung mit vielen Zeilen möchte ich doppelte Einträge überspringen, die sonst zu Fehlern führen würden. Nach einigen Nachforschungen scheinen meine Optionen die Verwendung von entweder:

  • ON DUPLICATE KEY UPDATE was eine unnötige Aktualisierung um einige Kosten bedeutet, oder
  • INSERT IGNORE was eine Einladung für andere Arten des Nichteintretens bedeutet.

Habe ich Recht in diesen Annahmen? Was ist der beste Weg, um einfach die Zeilen zu überspringen, die Duplikate verursachen könnten, und einfach zu den anderen Zeilen weiterzugehen?


Ich benutze routinemäßig INSERT IGNORE , und es klingt genau nach der Art von Verhalten, die Sie auch suchen. Solange Sie wissen, dass Zeilen, die Indexkonflikte verursachen würden, nicht eingefügt werden und Sie Ihr Programm dementsprechend planen, sollte es keine Probleme verursachen.


Ich weiß, das ist alt, aber ich werde diese Notiz hinzufügen, falls jemand (wie ich) auf dieser Seite ankommt, während sie versucht, Informationen zu INSERT..IGNORE zu finden.

Wie oben erwähnt, werden Fehler, die beim Ausführen der INSERT-Anweisung auftreten, stattdessen als Warnungen behandelt, wenn Sie INSERT..IGNORE verwenden.

Eine Sache, die nicht explizit erwähnt wird, ist, dass INSERT..IGNORE dazu führt, dass ungültige Werte beim Einfügen den engsten Werten angepasst werden (während ungültige Werte dazu führen würden, dass die Abfrage abgebrochen wird, wenn das Schlüsselwort IGNORE nicht verwendet wurde).


Mögliche Gefahr von INSERT IGNORE. Wenn Sie versuchen, den VARCHAR-Wert länger einzufügen, wurde die Spalte mit - definiert. Der Wert wird abgeschnitten und eingefügt, wenn der strikte Modus aktiviert ist.


Wenn Sie in die Tabelle und 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 :

Einfügen in Tabelle1 set column1 = a, column2 = b on dulplicate update column2 = c;

Nun, diese Insert-Anweisung kann anders aussehen, was Sie zuvor gesehen haben. Diese Einfügeanweisung versucht, eine Zeile in Tabelle1 mit dem Wert von a und b in Spalte spalte1 bzw. spalte2 einzufügen.

Lassen Sie uns diese Aussage tief verstehen:

Zum Beispiel: - hier ist Spalte1 als Primärschlüssel in Tabelle1 definiert.

Nun, wenn in Tabelle1 keine Zeile mit dem Wert "a" in Spalte1 vorhanden ist. Diese Anweisung fügt also eine Zeile in die Tabelle ein1.

Nun, wenn in Tabelle1 eine Zeile mit dem Wert "a" in Spalte2 vorhanden ist. Diese Anweisung aktualisiert also den column2-Wert der Zeile mit "c", wobei der Wert von column1 "a" ist.

Wenn Sie also eine neue Zeile einfügen möchten, aktualisieren Sie diese Zeile andernfalls auf den Konflikt des Primärschlüssels oder des eindeutigen Index. Lesen Sie mehr über diesen Link


Wenn Sie sehen wollen, was das alles bedeutet, hier ist ein Schlag von allem:

CREATE TABLE `users_partners` (
  `uid` int(11) NOT NULL DEFAULT '0',
  `pid` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`uid`,`pid`),
  KEY `partner_user` (`pid`,`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

Der Primärschlüssel basiert auf beiden Spalten dieser Schnellreferenztabelle. Ein Primärschlüssel erfordert eindeutige Werte.

Lass uns anfangen:

INSERT INTO users_partners (uid,pid) VALUES (1,1);
...1 row(s) affected

INSERT INTO users_partners (uid,pid) VALUES (1,1);
...Error Code : 1062
...Duplicate entry '1-1' for key 'PRIMARY'

INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1);
...0 row(s) affected

INSERT INTO users_partners (uid,pid) VALUES (1,1) ON DUPLICATE KEY UPDATE uid=uid
...0 row(s) affected

Beachten Sie, dass das oben genannte zu viel zusätzliche Arbeit gespart hat, indem Sie die Spalte auf sich selbst gestellt haben, keine Aktualisierung wird tatsächlich benötigt

REPLACE INTO users_partners (uid,pid) VALUES (1,1)
...2 row(s) affected

und jetzt einige mehrreihige Tests:

INSERT INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
...Error Code : 1062
...Duplicate entry '1-1' for key 'PRIMARY'

INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
...3 row(s) affected

In der Konsole wurden keine anderen Nachrichten generiert. Diese 4 Werte befinden sich nun in den Tabellendaten. Ich habe alles außer (1,1) gelöscht, damit ich aus dem gleichen Spielfeld testen konnte

INSERT INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4) ON DUPLICATE KEY UPDATE uid=uid
...3 row(s) affected

REPLACE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
...5 row(s) affected

So, da hast du es. Da dies alles auf einer frischen Tabelle mit fast keinen Daten und nicht in der Produktion durchgeführt wurde, waren die Ausführungszeiten mikroskopisch und irrelevant. Jeder, der Daten aus der realen Welt hat, wäre mehr als willkommen, sie beizutragen.


Replace Into scheint eine Option zu sein. Oder Sie können mit überprüfen

IF NOT EXISTS(QUERY) Then INSERT

Dies wird einfügen oder löschen dann einfügen. Ich tendiere dazu, zuerst einen IF NOT EXISTS Check zu machen.





insert