Ich weiß, dass Sie mehrere Zeilen gleichzeitig einfügen können. Gibt es eine Möglichkeit, mehrere Zeilen gleichzeitig (wie in einer Abfrage) in MySQL zu aktualisieren?
Bearbeiten: Zum Beispiel habe ich folgendes
Name id Col1 Col2
Row1 1 6 1
Row2 2 2 3
Row3 3 9 5
Row4 4 16 8
Ich möchte alle folgenden Updates in einer Abfrage zusammenfassen
UPDATE table SET Col1 = 1 WHERE id = 1;
UPDATE table SET Col1 = 2 WHERE id = 2;
UPDATE table SET Col2 = 3 WHERE id = 3;
UPDATE table SET Col1 = 10 WHERE id = 4;
UPDATE table SET Col2 = 12 WHERE id = 4;
mysql
sql
sql-update
Teifion
quelle
quelle
Da Sie dynamische Werte haben, müssen Sie für die zu aktualisierenden Spalten eine IF oder CASE verwenden. Es wird ein bisschen hässlich, aber es sollte funktionieren.
Anhand Ihres Beispiels können Sie Folgendes tun:
quelle
$commandTxt = 'UPDATE operations SET chunk_finished = CASE id '; foreach ($blockOperationChecked as $operationID => $operationChecked) $commandTxt .= " WHEN $operationID THEN $operationChecked "; $commandTxt .= 'ELSE id END WHERE id IN ('.implode(', ', array_keys(blockOperationChecked )).');';
Die Frage ist alt, aber ich möchte das Thema mit einer anderen Antwort erweitern.
Mein Punkt ist, der einfachste Weg, dies zu erreichen, besteht darin, mehrere Abfragen mit einer Transaktion zu versehen. Die akzeptierte Antwort
INSERT ... ON DUPLICATE KEY UPDATE
ist ein netter Hack, aber man sollte sich seiner Nachteile und Einschränkungen bewusst sein:"Field 'fieldname' doesn't have a default value"
MySQL-Warnung angezeigt, auch wenn Sie überhaupt keine einzelne Zeile einfügen. Es wird Sie in Schwierigkeiten bringen, wenn Sie sich dazu entschließen, streng zu sein und MySQL-Warnungen in Laufzeitausnahmen in Ihrer App umzuwandeln.Ich habe einige Leistungstests für drei der vorgeschlagenen Varianten durchgeführt, einschließlich der
INSERT ... ON DUPLICATE KEY UPDATE
Variante, einer Variante mit der Klausel "case / when / then" und einem naiven Ansatz mit Transaktion. Sie können die Python - Code und die Ergebnisse bekommen hier . Die allgemeine Schlussfolgerung ist, dass die Variante mit case-Anweisung doppelt so schnell ist wie zwei andere Varianten, aber es ist ziemlich schwierig, korrekten und injektionssicheren Code dafür zu schreiben. Ich persönlich halte mich daher an den einfachsten Ansatz: die Verwendung von Transaktionen.Bearbeiten: Die Ergebnisse von Dakusan beweisen, dass meine Leistungsschätzungen nicht ganz gültig sind. Bitte sehen Sie diese Antwort für eine weitere, ausführlichere Untersuchung.
quelle
Nicht sicher, warum eine andere nützliche Option noch nicht erwähnt wird:
quelle
Für InnoDB gilt Folgendes.
Ich halte es für wichtig, die Geschwindigkeit der drei verschiedenen Methoden zu kennen.
Es gibt 3 Methoden:
Ich habe das gerade getestet und die INSERT-Methode war für mich 6,7-mal schneller als die TRANSACTION-Methode. Ich habe sowohl 3.000 als auch 30.000 Zeilen ausprobiert.
Die TRANSACTION-Methode muss weiterhin jede einzelne Abfrage ausführen, was einige Zeit in Anspruch nimmt, obwohl sie die Ergebnisse während der Ausführung im Speicher oder so stapelt. Die TRANSACTION-Methode ist sowohl in Replikations- als auch in Abfrageprotokollen ziemlich teuer.
Schlimmer noch, die CASE-Methode war 41,1-mal langsamer als die INSERT-Methode mit 30.000 Datensätzen (6,1-mal langsamer als TRANSACTION). Und 75x langsamer in MyISAM. Die INSERT- und CASE-Methoden haben bei ~ 1.000 Datensätzen die Gewinnschwelle überschritten. Selbst bei 100 Datensätzen ist die CASE-Methode kaum schneller.
Im Allgemeinen halte ich die INSERT-Methode für die beste und einfachste Anwendung. Die Abfragen sind kleiner und leichter zu lesen und nehmen nur eine Aktionsabfrage auf. Dies gilt sowohl für InnoDB als auch für MyISAM.
Bonusmaterial:
Die Lösung für das Problem des INSERT-Nicht-Standardfelds besteht darin, die relevanten SQL-Modi vorübergehend auszuschalten :
SET SESSION sql_mode=REPLACE(REPLACE(@@SESSION.sql_mode,"STRICT_TRANS_TABLES",""),"STRICT_ALL_TABLES","")
. Stellen Sie sicher,sql_mode
dass Sie die erste speichern, wenn Sie sie zurücksetzen möchten.Was andere Kommentare betrifft, die besagen, dass das auto_increment mit der INSERT-Methode hochgefahren wird, scheint dies in InnoDB der Fall zu sein, nicht jedoch in MyISAM.
Der Code zum Ausführen der Tests lautet wie folgt. Es gibt auch .SQL-Dateien aus, um den Overhead des PHP-Interpreters zu beseitigen
quelle
Verwenden Sie eine temporäre Tabelle
quelle
Das sollte für dich funktionieren.
Das MySQL-Handbuch enthält eine Referenz für mehrere Tabellen.
quelle
Warum erwähnt niemand mehrere Anweisungen in einer Abfrage ?
In PHP verwenden Sie die
multi_query
Methode der MySQL-Instanz.Aus dem PHP-Handbuch
Hier ist das Ergebnis im Vergleich zu anderen 3 Methoden in Update 30.000 Raw. Code kann gefunden werden hier die auf Antwort von @Dakusan basiert
Transaktion: 5.5194580554962
Einfügen: 0.20669293403625
Fall: 16.474853992462
Multi: 0.0412278175354
Wie Sie sehen können, ist die Abfrage mehrerer Anweisungen effizienter als die höchste Antwort.
Wenn Sie folgende Fehlermeldung erhalten:
Möglicherweise müssen Sie die
max_allowed_packet
MySQL-Konfigurationsdatei auf meinem Computer erhöhen/etc/mysql/my.cnf
und dann MySQL neu starten.quelle
$mysqli->multi_query($sql)
dauerte "0" Sekunden. Nachfolgende Abfragen schlugen jedoch fehl, sodass ich dies zu einem separaten "Programm" machte.Sie können eine Einstellung namens "Multi-Anweisung" ändern, die den implementierten "Sicherheitsmechanismus" von MySQL deaktiviert, um (mehr als einen) Injektionsbefehl zu verhindern. Typisch für die "brillante" Implementierung von MySQL, verhindert es auch, dass Benutzer effiziente Abfragen durchführen.
Hier ( http://dev.mysql.com/doc/refman/5.1/en/mysql-set-server-option.html ) finden Sie einige Informationen zur C-Implementierung der Einstellung.
Wenn Sie PHP verwenden, können Sie mit mysqli mehrere Anweisungen ausführen (ich glaube, php wird bereits seit einiger Zeit mit mysqli ausgeliefert).
Ich hoffe, das hilft.
quelle
mysqli::begin_transaction(..)
Vor undmysql::commit(..)
nach dem Senden der Abfrage verwenden . Oder verwenden SieSTART TRANSACTION
als erste undCOMMIT
als letzte Anweisung in der Abfrage selbst.Sie können dieselbe Tabelle als Alias verwenden, um die IDs anzugeben, nach denen Sie einfügen möchten (wenn Sie eine zeilenweise Aktualisierung durchführen:
Darüber hinaus sollte es offensichtlich sein, dass Sie auch von anderen Tabellen aus aktualisieren können. In diesem Fall wird das Update auch als "SELECT" -Anweisung verwendet, sodass Sie die Daten aus der von Ihnen angegebenen Tabelle erhalten. Sie geben in Ihrer Abfrage explizit die Aktualisierungswerte an, sodass die zweite Tabelle nicht betroffen ist.
quelle
Möglicherweise möchten Sie auch Joins für Updates verwenden, was ebenfalls möglich ist.
Bearbeiten: Wenn die Werte, die Sie aktualisieren, nicht von einer anderen Stelle in der Datenbank stammen, müssen Sie mehrere Aktualisierungsabfragen ausführen.
quelle
Und jetzt der einfache Weg
quelle
verwenden
Bitte beachten Sie:
quelle
Im Folgenden werden alle Zeilen in einer Tabelle aktualisiert
Im nächsten Schritt werden alle Zeilen aktualisiert, in denen der Wert von Spalte 2 mehr als 5 beträgt
Es gibt alle Beispiele von Unkwntech zum Aktualisieren von mehr als einer Tabelle
quelle
Ja. Dies ist mit der SQL-Anweisung INSERT ON DUPLICATE KEY UPDATE möglich. Syntax: INSERT INTO Tabellenname (a, b, c) VALUES (1,2,3), (4,5,6) ON DUPLICATE KEY UPDATE a = WERTE (a), b = WERTE (b), c = WERTE (c)
quelle
Dies sollte das erreichen, wonach Sie suchen. Fügen Sie einfach weitere IDs hinzu. Ich habe es getestet.
quelle
// Du baust es einfach in PHP wie
So können Sie die Lochtabelle mit einer Abfrage aktualisieren
quelle
something
aufsomething
)