Ich begann mit googeln und fand diesen Artikel, der sich mit Mutex-Tabellen befasst.
Ich habe einen Tisch mit ~ 14 Millionen Datensätzen. Wenn ich weitere Daten im selben Format hinzufügen möchte, gibt es eine Möglichkeit, um sicherzustellen, dass der Datensatz, den ich einfügen möchte, nicht bereits vorhanden ist, ohne zwei Abfragen zu verwenden (dh eine zu überprüfende Abfrage und eine einzufügende Abfrage ist die Ergebnismenge leeren)?
unique
Garantiert eine Einschränkung für ein Feld, dass der insert
Wille fehlschlägt, wenn er bereits vorhanden ist?
Es scheint, dass mit nur einer Einschränkung, wenn ich die Einfügung über PHP ausstelle, das Skript krächzt.
mysql
sql
primary-key
sql-insert
Labyrinth
quelle
quelle
Antworten:
verwenden
INSERT IGNORE INTO table
Siehe http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html
Es gibt auch
INSERT … ON DUPLICATE KEY UPDATE
Syntax, Erklärungen finden Sie auf dev.mysql.comPost von bogdan.org.ua gemäß Googles Webcache :
quelle
INSERT … ON DUPLICATE KEY UPDATE
ist besser, da die Zeile nicht gelöscht wird undauto_increment
Spalten und andere Daten erhalten bleiben.INSERT … ON DUPLICATE KEY UPDATE
Methode wird jede AUTO_INCREMENT-Spalte mit fehlgeschlagener Einfügung erhöht. Wahrscheinlich, weil es nicht wirklich gescheitert ist, aber UPDATE'd.Lösung:
Erläuterung:
Die innerste Abfrage
WHERE NOT EXISTS
Wird als Bedingung verwendet, wird erkannt, ob bereits eine Zeile mit den einzufügenden Daten vorhanden ist. Nachdem eine Zeile dieser Art gefunden wurde, wird die Abfrage möglicherweise gestoppt, daher kann dieLIMIT 1
(Mikrooptimierung, weggelassen werden).Die Zwischenabfrage
repräsentiert die einzufügenden Werte.
DUAL
bezieht sich auf eine spezielle Tabelle mit einer Zeile und einer Spalte, die standardmäßig in allen Oracle-Datenbanken vorhanden ist (siehe https://en.wikipedia.org/wiki/DUAL_table ). Auf einem MySQL-Server Version 5.7.26 habe ich beim Auslassen eine gültige Abfrage erhaltenFROM DUAL
, aber ältere Versionen (wie 5.5.60) scheinen dieFROM
Informationen zu benötigen . Bei VerwendungWHERE NOT EXISTS
der Zwischenabfrage wird eine leere Ergebnismenge zurückgegeben, wenn die innerste Abfrage übereinstimmende Daten gefunden hat.Die äußere Abfrage
Fügt die Daten ein, falls diese von der Zwischenabfrage zurückgegeben werden.
quelle
INSERT IGNORE
undINSERT ON DUPLICATE KEY
eindeutige Schlüsseleinschränkungen erforderlich sind)stuff for value1
undstuff for value2
identisch sind? Dies würde einDuplicate column name
SELECT 1
anstattSELECT *
in den Unterabfragen. Viel wahrscheinlicher, dass dies durch einen Index erfüllt werden kann.Bei doppelter Schlüsselaktualisierung oder Einfügen ignorieren können mit MySQL praktikable Lösungen sein.
Beispiel für ein Update eines doppelten Schlüsselupdates basierend auf mysql.com
Beispiel für das Ignorieren von Einfügungen basierend auf mysql.com
Oder:
Oder:
quelle
Jede einfache Einschränkung sollte den Job erledigen, wenn eine Ausnahme akzeptabel ist. Beispiele:
Entschuldigung, das scheint täuschend einfach zu sein. Ich weiß, dass es angesichts des Links, den Sie mit uns teilen, schlecht aussieht. ;-(
Aber ich gebe diese Antwort trotzdem, weil sie Ihr Bedürfnis zu befriedigen scheint. (Wenn nicht, kann dies dazu führen, dass Sie Ihre Anforderungen aktualisieren. Dies wäre auch "eine gute Sache" (TM).)
Bearbeitet : Wenn eine Einfügung die Datenbankeinschränkung aufheben würde, wird auf Datenbankebene eine Ausnahme ausgelöst, die vom Treiber weitergeleitet wird. Es wird sicherlich Ihr Skript mit einem Fehler stoppen. In PHP muss es möglich sein, diesen Fall anzusprechen ...
quelle
INSERT IGNORE
Grundsätzlich werden alle Fehler in Warnungen umgewandelt, damit Ihr Skript nicht unterbrochen wird. Sie können dann alle Warnungen mit dem Befehl anzeigenSHOW WARNINGS
. Und noch ein wichtiger Hinweis : UNIQUE-Einschränkungen funktionieren nicht mit NULL-Werten, d. H. row1 (1, NULL) und row2 (1, NULL) werden beide eingefügt (es sei denn, eine andere Einschränkung wie ein Primärschlüssel ist fehlerhaft). Unglücklich.Hier ist eine PHP-Funktion, die nur dann eine Zeile einfügt, wenn nicht alle angegebenen Spaltenwerte in der Tabelle vorhanden sind.
Wenn sich eine der Spalten unterscheidet, wird die Zeile hinzugefügt.
Wenn die Tabelle leer ist, wird die Zeile hinzugefügt.
Wenn eine Zeile vorhanden ist, in der alle angegebenen Spalten die angegebenen Werte haben, wird die Zeile nicht hinzugefügt.
Anwendungsbeispiel:
quelle
mysql_*
Erweiterung ist ab PHP 5.5.0 veraltet und wurde ab PHP 7.0.0 entfernt. Stattdessen sollte entweder die Erweiterung mysqli oder PDO_MySQL verwendet werden. Weitere Hilfe bei der Auswahl einer MySQL-API finden Sie in der MySQL-API-Übersicht .Wenn der Datensatz vorhanden ist, wird er überschrieben. Wenn es noch nicht existiert, wird es erstellt.
quelle
REPLACE
kann die Zeile löschen und dann anstelle der Aktualisierung einfügen. Der Nebeneffekt ist, dass Einschränkungen andere Objekte löschen und Löschauslöser ausgelöst werden können.Versuche Folgendes:
quelle
Es gibt verschiedene Antworten, die beschreiben, wie Sie dieses Problem lösen können, wenn Sie einen
UNIQUE
Index haben, mit dem SieON DUPLICATE KEY
oder vergleichen könnenINSERT IGNORE
. Dies ist nicht immer der Fall, und aufgrundUNIQUE
einer Längenbeschränkung (1000 Byte) können Sie dies möglicherweise nicht ändern. Zum Beispiel musste ich mit Metadaten in WordPress (wp_postmeta
) arbeiten.Ich habe es endlich mit zwei Fragen gelöst:
Abfrage 1 ist eine reguläre
UPDATE
Abfrage ohne Auswirkung, wenn das betreffende Dataset nicht vorhanden ist. Abfrage 2 ist eine,INSERT
die von a abhängtNOT EXISTS
, dh dieINSERT
wird nur ausgeführt, wenn der Datensatz nicht vorhanden ist.quelle
Bemerkenswert ist, dass INSERT IGNORE den Primärschlüssel immer noch erhöht, unabhängig davon, ob die Anweisung erfolgreich war oder nicht, wie dies bei einem normalen INSERT der Fall wäre.
Dies führt zu Lücken in Ihren Primärschlüsseln, die einen Programmierer psychisch instabil machen können. Wenn Ihre Anwendung schlecht gestaltet ist und von perfekten inkrementellen Primärschlüsseln abhängt, kann dies zu Kopfschmerzen führen.
Schauen Sie nach
innodb_autoinc_lock_mode = 0
(Servereinstellung und mit einem leichten Leistungseinbruch) oder verwenden Sie zuerst ein SELECT, um sicherzustellen, dass Ihre Abfrage nicht fehlschlägt (was auch einen Leistungseinbruch und zusätzlichen Code beinhaltet).quelle
SELECT
Niederlage der ganze Zweck, nur eine große Menge vonINSERT
s abzugeben und sich nicht um Duplikate sorgen zu wollen.Aktualisieren oder einfügen ohne bekannten Primärschlüssel
Wenn Sie bereits einen eindeutigen oder Primärschlüssel haben, funktionieren die anderen Antworten entweder
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
oderREPLACE INTO ...
sollten einwandfrei funktionieren (beachten Sie, dass das Ersetzen in Löschungen, falls vorhanden, und das Einfügen - vorhandene Werte werden daher nicht teilweise aktualisiert).Aber wenn Sie die Werte für
some_column_id
und habensome_type
, deren Kombination als eindeutig bekannt ist. Und Sie möchten aktualisieren,some_value
wenn vorhanden, oder einfügen, wenn nicht vorhanden. Und Sie möchten dies in nur einer Abfrage tun (um die Verwendung einer Transaktion zu vermeiden). Dies könnte eine Lösung sein:Grundsätzlich wird die Abfrage folgendermaßen ausgeführt (weniger kompliziert als es aussehen mag):
WHERE
Klauselübereinstimmung aus.s
), in der die Spaltenwerte explizit angegeben werden (s.id ist NULL, sodass eine neue automatische Inkrement-ID generiert wird).s
verworfen (aufgrund von LIMIT 1 in der Tabellet
) und es wird immer eine ausgelöst,ON DUPLICATE KEY
dieUPDATE
diesome_value
Spalte enthält.s
).Hinweis: Jede Tabelle in einer relationalen Datenbank sollte mindestens eine primäre
id
Spalte für die automatische Inkrementierung enthalten . Wenn Sie dies nicht haben, fügen Sie es hinzu, auch wenn Sie es auf den ersten Blick nicht benötigen. Es wird definitiv für diesen "Trick" benötigt.quelle
INSERT INTO ... SELECT FROM
Format angeboten. Warum hast du auch?INSERT INTO... SELECT FROM...
Lösung. Bitte verweisen Sie auf einen Link zu einer Antwort, die dieselbe ist. Wenn Sie sie finden, werde ich diese Antwort löschen. Andernfalls stimmen Sie meiner Antwort zu (Deal?). Stellen Sie sicher, dass die Antwort, die Sie verknüpfen möchten, nur 1 Abfrage (für Aktualisierung + Einfügen) und keine Transaktion verwendet und auf eine beliebige Kombination von Spalten abzielen kann, von denen bekannt ist, dass sie eindeutig sind (daher sind die Spalten separat nicht vorhanden) müssen einzigartig sein).