Um die Antwort von MguerraTorres zu erweitern :
(Aktualisiert mit den Informationen aus Ihrer sekundären Abfrage)
In Ihrer ersten Abfrage UPDATE cte
heißt es, die Tabelle vom CTE zu aktualisieren.
FROM cte as a
sagt, auf die Tabelle aus dem CTE als zu verweisen a
.
Wir haben uns also an zwei Stellen auf unseren CTE bezogen.
Was Sie möglicherweise nicht bemerken, ist, dass ein CTE jedes Mal neu bewertet wird, wenn er in Ihrer Abfrage angezeigt wird, als hätten Sie die Referenz durch eine Unterabfrage ersetzt. Da Sie zweimal auf den CTE verwiesen haben, haben Sie zwei separate Ergebnismengen generiert , mit denen die DB-Engine arbeiten kann.
Wenn Sie sagen, b.Value
wo zu verwenden a.ID = b.ID
, haben wir zwei Zeilen - eine mit b.Value
100 und eine mit 200 - aus der Tabelle b
und aus unserer zweiten CTE-Ergebnismenge.
Wir aktualisieren jedoch die erste CTE-Ergebnismenge basierend auf diesen beiden Zeilen. Daher wird jede Zeile in dieser ersten Ergebnismenge aus den beiden zurückgegebenen Zeilen aktualisiert . Es gibt keine Beziehung zwischen den beiden Ergebnismengen, obwohl sie dieselben zugrunde liegenden Daten darstellen. Die Engine führt CROSS JOIN
zwischen den Ergebnissen Ihres Joins und der ersten Ergebnismenge einen Vorgang durch, um die Aktualisierung durchzuführen.
Ihre UPDATE
Anweisung aktualisiert beide Zeilen auf 200 und dann auf 100 (da die Engine entscheidet, wie die gekreuzten Zeilen am schnellsten angewendet werden sollen, werden sie möglicherweise nicht in der Reihenfolge angezeigt, in der sie eingegeben wurden). Beide Zeilen werden auf denselben Wert aktualisiert, da sie aus denselben mehreren Zeilen aktualisiert werden.
Ihre erste Abfrage ist funktional identisch mit:
DECLARE @a TABLE (ID int, Value int);
DECLARE @b TABLE (ID int, Value int);
INSERT @a VALUES (1, 10), (2, 20);
INSERT @b VALUES (1, 100),(2, 200);
WITH cte AS
(
SELECT * FROM @a
)
UPDATE cte
SET Value = b.Value
FROM (SELECT * FROM @a) AS a
INNER JOIN @b AS b
ON b.ID = a.ID
SELECT * FROM @a
GO
In Ihrer zweiten Abfrage, weiß die DB - Engine , dass beide a
und @a
eine Tabelle außerhalb der Abfrage verweisen, und sie weiß , dass a
und @a
das gleiche bedeuten, so ist es richtig , die Reihen von bindet @b
zu , @a
wenn das Update durchführen.
In den Kommentaren haben Sie gefragt:
Wäre das Ergebnis für beide immer 100? oder kann es manchmal 200 für beide sein - Wie ich sehe, gibt es hier keine klare Regel?
Ob es 100 oder 200 ist, kann variieren.
Ich würde sagen, dass es wahrscheinlich ist, dass Sie mit den gleichen Aussagen, die in Ihrer ersten Abfrage gezeigt wurden und auf die gleiche Weise ausgeführt wurden, mit ziemlicher Sicherheit das gleiche Ergebnis erzielen würden.
In der realen Welt, in der Tabellen andere Aktivitäten sehen, konnte man jedoch nicht wirklich das eine oder andere Ergebnis erzielen, insbesondere im Laufe der Zeit. Dies hängt davon ab, wie die DB-Engine mit den Tabellen im Join übereinstimmt und dann die Zeilen beim Anwenden des Updates verarbeitet.
Einfacher Fehler beim Aliasing von cte mit "a"
Sie sollten "a" aktualisieren, anstatt "cte" zu aktualisieren.
quelle