MySQL, aktualisieren Sie mehrere Tabellen mit einer Abfrage

130

Ich habe eine Funktion, die drei Tabellen aktualisiert, aber ich verwende drei Abfragen, um dies auszuführen. Ich möchte einen bequemeren Ansatz für bewährte Verfahren verwenden.

Wie kann ich mehrere Tabellen in MySQL mit einer einzigen Abfrage aktualisieren?

Adamski
quelle
3
Können Sie ein Beispiel für den generierten Code angeben? Gibt es einen gemeinsamen Schlüssel zwischen den Tabellen?
Jonathan Day

Antworten:

451

Nehmen Sie den Fall von zwei Tabellen Booksund Orders. Wenn wir die Anzahl der Bücher in einer bestimmten Reihenfolge mit Order.ID = 1002in Orderstable erhöhen, müssen wir auch die Gesamtzahl der in unserem Bestand verfügbaren Bücher um dieselbe Anzahl in Bookstable reduzieren .

UPDATE Books, Orders
SET Orders.Quantity = Orders.Quantity + 2,
    Books.InStock = Books.InStock - 2
WHERE
    Books.BookID = Orders.BookID
    AND Orders.OrderID = 1002;
Irfan
quelle
Wenn ich "LIMIT" in die SQL-Abfrage aufnehmen möchte, muss ich LIMIT 1 oder LIMIT 2 sagen?
Bluedayz
2
Was ist der Vorteil gegenüber einer Transaktion? Vielen Dank!
Paulkon
2
@paulkon, ich gehe davon aus, dass bei der Verwendung von Transaktionen viel Aufwand anfällt, da Rollbacks verfügbar sein müssen, wenn eine Prozedur in der Transaktion fehlschlägt.
Thijs Riezebeek
27
Allgemeine Warnung bei Verwendung dieser Abfrage. Die WHERE-Klausel wird für jede Tabelle separat ausgewertet. Die Books.BookID = Orders.BookID ist sehr wichtig, ohne sie würde die Aktualisierung der Books-Tabelle für alle Zeilen und nicht nur für die Zeile mit der angegebenen ID erfolgen. Einige Lektionen werden auf die harte Tour gelernt, diese wurde auf erschreckende Weise gelernt.
Nheimann1
1
@ nheimann1 Und genau deshalb empfehle ich immer, die ANSI-Syntax "Inner Join" zu verwenden. Es ist zu leicht, diesen Zustand zu vergessen und stattdessen einen vollständigen kartesischen Beitritt zu erhalten.
narr4jesus
76
UPDATE t1
INNER JOIN t2 ON t2.t1_id = t1.id
INNER JOIN t3 ON t2.t3_id = t3.id
SET t1.a = 'something',
    t2.b = 42,
    t3.c = t2.c
WHERE t1.a = 'blah';

Um zu sehen, was hier aktualisiert wird, können Sie dies in eine select-Anweisung konvertieren, z.

SELECT t2.t1_id, t2.t3_id, t1.a, t2.b, t2.c AS t2_c, t3.c AS t3_c
FROM t1
INNER JOIN t2 ON t2.t1_id = t1.id
INNER JOIN t3 ON t2.t3_id = t3.id
WHERE t1.a = 'blah';

Ein Beispiel mit denselben Tabellen wie die andere Antwort:

SELECT Books.BookID, Orders.OrderID,
    Orders.Quantity AS CurrentQuantity,
    Orders.Quantity + 2 AS NewQuantity,
    Books.InStock AS CurrentStock,
    Books.InStock - 2 AS NewStock
FROM Books
INNER JOIN Orders ON Books.BookID = Orders.BookID
WHERE Orders.OrderID = 1002;

UPDATE Books
INNER JOIN Orders ON Books.BookID = Orders.BookID
SET Orders.Quantity = Orders.Quantity + 2,
    Books.InStock = Books.InStock - 2
WHERE Orders.OrderID = 1002;

BEARBEITEN:

Fügen wir zum Spaß etwas Interessanteres hinzu.

Angenommen, Sie haben eine Tabelle von booksund eine Tabelle von authors. Du bookshast eine author_id. Bei der ursprünglichen Erstellung der Datenbank wurden jedoch keine Fremdschlüsseleinschränkungen eingerichtet. Später führte ein Fehler im Front-End-Code dazu, dass einige Bücher mit ungültigen author_ids hinzugefügt wurden . Als DBA möchten Sie nicht alle diese Punkte durchgehen müssen, um bookszu überprüfen, was author_idsein soll. Daher wird die Entscheidung getroffen, dass die Datenerfassungsgeräte den booksHinweis nach rechts korrigieren authors. Aber es gibt zu viele Bücher, um sie durchzugehen, und sagen wir, Sie wissen, dass diejenigen, die eine haben author_id, die einer tatsächlichen entspricht, authorkorrekt sind. Es sind nur diejenigen, die nicht existierenauthor_ids, die ungültig sind. Es gibt bereits eine Benutzeroberfläche, über die die Benutzer die Buchdetails aktualisieren können, und die Entwickler möchten dies nicht nur für dieses Problem ändern. Da die vorhandene Benutzeroberfläche dies jedoch tut INNER JOIN authors, werden alle Bücher mit ungültigen Autoren ausgeschlossen.

Was Sie tun können, ist Folgendes: Fügen Sie einen gefälschten Autorendatensatz wie "Unbekannter Autor" ein. Aktualisieren Sie dann author_idalle fehlerhaften Datensätze, um auf den unbekannten Autor zu verweisen. Anschließend können die Datenerfassungsgeräte nach allen Büchern suchen, bei denen der Autor auf "Unbekannter Autor" eingestellt ist, den richtigen Autor suchen und diese korrigieren.

Wie aktualisieren Sie alle fehlerhaften Datensätze, um auf den unbekannten Autor zu verweisen? So (vorausgesetzt, der unbekannte Autor author_idist 99999):

UPDATE books
LEFT OUTER JOIN authors ON books.author_id = authors.id
SET books.author_id = 99999
WHERE authors.id IS NULL;

Die oben genannten werden auch aktualisiert books, die einen NULL author_idan den unbekannten Autor haben. Wenn Sie das nicht wollen, können Sie natürlich hinzufügen AND books.author_id IS NOT NULL.

Wodin
quelle
35

Sie können dies auch mit einer Abfrage tun, indem Sie einen Join wie folgt verwenden:

UPDATE table1,table2 SET table1.col=a,table2.col2=b
WHERE items.id=month.id;

Und dann senden Sie einfach diese eine Anfrage. Weitere Informationen zu Joins finden Sie hier: http://dev.mysql.com/doc/refman/5.0/en/join.html . Es gibt auch einige Einschränkungen für die Bestellung und Einschränkung mehrerer Tabellenaktualisierungen, über die Sie hier lesen können: http://dev.mysql.com/doc/refman/5.0/en/update.html (nur Strg + F "Join").

Stephen Searles
quelle
Es ist ein bisschen großzügig, das als "Join" zu bezeichnen ;-)
underscore_d
2

Dafür sind gespeicherte Prozeduren normalerweise gedacht: um mehrere SQL-Anweisungen in einer Sequenz zu implementieren. Mithilfe von Rollbacks können Sie sicherstellen, dass sie als eine Arbeitseinheit behandelt werden, dh entweder alle oder keine ausgeführt werden, um die Datenkonsistenz zu gewährleisten.

SteveCav
quelle
Wo würde ich die Prozedur schreiben? Könnten Sie bitte ein Beispiel geben?
Adamski
1
Für die Erklärung der Notwendigkeit der Atomizität nach oben gestimmt - es ist auch wichtig zu wissen, dass die Verwendung gespeicherter Prozeduren nicht allein die Konsistenz garantiert, sondern dass Sie weiterhin Transaktionen verwenden müssen. Ebenso können Transaktionen ohne Verwendung einer gespeicherten Prozedur ausgeführt werden, vorausgesetzt, sie werden über dieselbe Verbindung ausgeführt. In diesem Fall ist die Verwendung eines Multi-Table-Updates noch besser.
Duncan
2

Wenn Sie mehrere Abfragen sagen, meinen Sie mehrere SQL-Anweisungen wie folgt:

UPDATE table1 SET a=b WHERE c;
UPDATE table2 SET a=b WHERE d;
UPDATE table3 SET a=b WHERE e;

Oder mehrere Abfragefunktionsaufrufe wie in:

mySqlQuery(UPDATE table1 SET a=b WHERE c;)
mySqlQuery(UPDATE table2 SET a=b WHERE d;)
mySqlQuery(UPDATE table3 SET a=b WHERE e;)

Ersteres kann mit einem einzigen mySqlQuery-Aufruf durchgeführt werden. Wenn Sie dies erreichen möchten, rufen Sie einfach die mySqlQuery-Funktion auf folgende Weise auf:

mySqlQuery(UPDATE table1 SET a=b WHERE c; UPDATE table2 SET a=b WHERE d; UPDATE table3 SET a=b WHERE e;)

Dadurch werden alle drei Abfragen mit einem Aufruf von mySqlQuery () ausgeführt.

code_burgar
quelle
mySqlQuery () ist eine benutzerdefinierte Funktion oder eine integrierte Funktion? Ich möchte mehr darüber wissen.
Debashis
3
Es gibt keinen signifikanten Unterschied zwischen dem Senden von drei Abfragen einzeln oder als Mehrfachabfrage, außer wenn Ihre Abfragefunktion jedes Mal eine neue Verbindung öffnet. Unter dem Gesichtspunkt der serverseitigen Ausführung ist es dasselbe
Duncan