Eine Unterabfrage ist eine leistungsstarke Möglichkeit, die Daten zu finden, die Sie für eine andere Abfrage verwenden möchten. Sie werden häufig in SELECT- und UPDATE-Anweisungen verwendet, um diese Abfragen effizienter und einfacher zu warten.
Es gibt verschiedene Möglichkeiten, Unterabfragen in UPDATE-Anweisungen zu verwenden. Werfen wir einen Blick auf jeden von ihnen.
SET und Unterabfrage
Die erste Methode, die wir uns ansehen werden, ist die Verwendung einer Unterabfrage in der SET-Klausel einer UPDATE-Anweisung.
Nehmen wir an, wir hätten eine Tabelle mit Produkten, die so aussah:
[Tabellen-ID=29 /]
Es speichert einige Informationen über verschiedene Produkte, die ein Unternehmen verkauft.
Angenommen, das Unternehmen hat beschlossen, den Preis des Produkts „Couch“ (Produkt-ID 1) zu erhöhen. Anstatt jedoch einen bestimmten Preis festzulegen, möchten sie diesen 20 % höher machen als das teuerste Produkt, das sie haben.
Dazu können wir eine Unterabfrage in der SET-Klausel verwenden. Wir könnten separate Anweisungen verwenden, aber es ist einfacher, eine einzige Anweisung zu verwenden.
Unsere Anweisung würde wie folgt aussehen:
UPDATE product SET price = ( SELECT MAX(price) * 1.2 FROM product ) WHERE product_id = 1;
Sie können sehen, dass die SET-Klausel eine Unterabfrage enthält, die den MAX-Wert der Preisspalte in der Produkttabelle findet und ihn mit 1,2 multipliziert, um 20 % hinzuzufügen. Schließlich befindet sich die WHERE-Klausel außerhalb der Unterabfrage, um nur die product_id von 1 zu aktualisieren, da sie eher für UPDATE als für die Unterabfrage gilt.
Dies führt zu folgender Änderung:
[Tabellen-ID=30 /]
SET und korrelierte Unterabfrage
Eine andere Möglichkeit, eine Unterabfrage in einer UPDATE-Anweisung zu verwenden, ist die Verwendung einer korrelierten Unterabfrage.
Es funktioniert ähnlich wie im vorherigen Beispiel. Eine korrelierte Unterabfrage ist jedoch eine Unterabfrage, die sich auf die äußere Anweisung bezieht und Teil einer UPDATE-Anweisung sein kann.
Anhand der Daten aus dem vorherigen Beispiel (der Produkttabelle) möchte das Unternehmen alle Produkte deaktivieren, für die keine Bestellung aufgegeben wurde. Die Daten dazu werden in der Tabelle order_line gespeichert.
Wenn wir es als korrelierte Unterabfrage geschrieben haben, sieht die Abfrage so aus:
UPDATE product p SET active = ( SELECT CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE 'N' END FROM order_line o WHERE o.product_id = p.product_id );
Die Unterabfrage führt eine COUNT-Funktion mit einer CASE-Anweisung aus, um zu bestimmen, ob der zurückgegebene Wert Y oder N ist, abhängig vom Wert von COUNT. Sie wird für jede product_id berechnet und entspricht der äußeren Abfrage.
Dadurch wird die aktive Spalte für einige Produkte auf Y und andere auf N gesetzt:
[Tabellen-ID=31 /]
WHERE Größer als Unterabfrage
Es ist auch möglich, eine Unterabfrage in der WHERE-Klausel zu verwenden. Genau wie in den vorherigen Beispielen kann dies getan werden, um den separaten Schritt des Suchens eines zu aktualisierenden Werts zu entfernen und dann die Abfrage auszuführen, um ihn zu aktualisieren.
Wir können mit unserem Beispiel aus den vorherigen Schritten weiterarbeiten. Angenommen, das Unternehmen möchte Produkte aktivieren, die einen überdurchschnittlichen Preis haben. Dazu können wir der WHERE-Klausel eine Unterabfrage hinzufügen.
Deaktivieren Sie zunächst alle Produkte.
UPDATE product SET active = ’N’;
Aktualisieren Sie dann die Tabelle mit unserer Unterabfrage.
UPDATE product SET active = 'Y' WHERE price > ( SELECT AVG(price) FROM product );
Dadurch wird der aktive Wert für alle Datensätze mit einem überdurchschnittlichen Preis auf Y gesetzt.
Die Tabelle sieht jetzt so aus:
[Tabellen-ID=32 /]
Es zeigt 2 Datensätze mit einem aktiven Wert von Y, weil sie überdurchschnittlich sind.
Diese Art von Abfrage kann auch mit anderen Operatoren ausgeführt werden, die einen einzelnen Wert zulassen, wie z. B.
WHERE IN Unterabfrage
Außerdem können wir eine Unterabfrage mit einem IN-Operator in der WHERE-Klausel verwenden.
Dies ähnelt dem vorherigen Beispiel, in dem der Größer-als-Operator für einen einzelnen Wert verwendet wurde. Der IN-Operator kann auf mehrere Werte angewendet werden.
Angenommen, das Unternehmen wollte den Preis einiger Produkte aktualisieren, die die einzigen Artikel in der Kategorie waren. Die Preise müssten halbiert werden.
Unsere Abfrage könnte so aussehen:
UPDATE product SET price = price / 2 WHERE category_id IN ( SELECT category_id FROM product GROUP BY category_id HAVING COUNT(*) = 1 );
Die Unterabfrage findet alle category_id-Werte, bei denen COUNT 1 ist. Wir müssen COUNT nicht im SELECT-Teil der Unterabfrage haben, aber wenn wir dies tun, zeigt die Abfrage einen Fehler an.
Die UPDATE-Anweisung aktualisiert den Preis, wenn die Kategorie die Kriterien der Unterabfrage erfüllt.
Unsere Ergebnisse sehen dann so aus:
[Tabellen-ID=33 /]
Die Daten sehen sehr ähnlich aus. Der Preis des Produkts mit der Kategorie-ID 1 wurde jedoch auf die Hälfte seiner ursprünglichen Kosten aktualisiert, da es das einzige Produkt in seiner Kategorie ist.
UPDATE-Unterabfrage
Schließlich können Sie eine Unterabfrage in einer UPDATE-Anweisung für die zu aktualisierende Tabelle verwenden.
In den vorherigen Beispielen haben wir nur die Produkttabelle verwendet. Sie können jedoch anstelle der Produkttabelle eine Unterabfrage verwenden, die eine Ergebnismenge zurückgibt, die aktualisiert werden kann.
Die Ergebnismenge muss aktualisierbar sein, ähnlich dem Fall, wenn Sie ein VIEW-Objekt erstellen und versuchen, es zu aktualisieren. Es muss einfach sein und den Primärschlüssel enthalten.
Nehmen wir also anhand unserer vorherigen Beispiele an, dass das Unternehmen die Kategorie für alle Produkte der Kategorie 4 in Kategorie 5 ändern möchte.
Unsere Abfrage könnte so aussehen:
UPDATE ( SELECT product_id, category_id FROM product) SET category_id = 5 WHERE category_id = 4;
Es ist ein einfaches Beispiel, das das Konzept demonstriert. Die Tabelle wurde durch die SELECT-Anweisung ersetzt, die nur zwei Spalten der Tabelle anzeigt.
Die Ergebnisse dieser Abfrage wären:
[Tabellen-ID=34 /]
Das gleiche Ergebnis könnte erhalten werden, indem die WHERE-Klausel in die UPDATE-Anweisung verschoben wird:
UPDATE ( SELECT product_id, category_id FROM product WHERE category_id = 4) SET category_id = 5;
Schlussfolgerung
Die Verwendung einer Unterabfrage in einer UPDATE-Anweisung kann eine gute Möglichkeit sein, die Wartbarkeit Ihrer Abfragen zu verbessern. Es kann auch die Anzahl der Schritte reduzieren, die zum Aktualisieren Ihrer Daten erforderlich sind, indem zwei oder mehr Abfragen zu einer einzigen Abfrage komprimiert werden.