Die Semantik der beiden Aussagen ist unterschiedlich:
- Das erste setzt den Wert der Variablen nicht, wenn keine Zeile gefunden wird.
- Die zweite Option setzt die Variable immer auf null, auch wenn keine Zeile gefunden wird.
Der konstante Scan erzeugt eine leere Zeile (ohne Spalten!), Die dazu führt, dass die Variable aktualisiert wird, falls nichts mit der Basistabelle übereinstimmt. Der linke Join stellt sicher, dass die leere Zeile den Join überlebt. Man kann sich vorstellen, dass die Variablenzuweisung am Stammknoten des Ausführungsplans stattfindet.
Verwenden SELECT @result
-- Set initial value
DECLARE @result uniqueidentifier = {guid 'FE2CA909-1162-4C6C-A7AC-33B257E28539'};
-- @result does not change
SELECT @result = AccountId
FROM Accounts
WHERE AccountId={guid '7AD4D33C-1ED7-4183-B7F3-48C33D666525'};
SELECT @result;
Verwenden SET @result
-- Set initial value
DECLARE @result uniqueidentifier = {guid 'FE2CA909-1162-4C6C-A7AC-33B257E28539'};
-- @result set to null
SET @result =
(
SELECT AccountId
FROM Accounts
WHERE AccountId={guid '7AD4D33C-1ED7-4183-B7F3-48C33D666525'}
);
SELECT @result;
Ausführungspläne
Am Wurzelknoten kommt keine Zeile an, daher erfolgt keine Zuweisung.
Eine Zeile kommt immer am Wurzelknoten an, sodass eine variable Zuordnung erfolgt.
Die zusätzlichen Funktionen Constant Scan und Nested Loops Left Outer Join sind kein Grund zur Sorge. Insbesondere der Join ist kostengünstig, da er am äußeren Eingang garantiert auf eine Zeile und am inneren Eingang (in Ihrem Beispiel) auf höchstens eine Zeile trifft.
Es gibt andere Möglichkeiten, um sicherzustellen, dass eine Zeile aus der Unterabfrage generiert wird, um sicherzustellen, dass eine Variablenzuweisung erfolgt. Eine Möglichkeit besteht darin, ein redundantes Skalaraggregat zu verwenden (keine Gruppenklausel):
-- Set initial value
DECLARE @result uniqueidentifier = {guid 'FE2CA909-1162-4C6C-A7AC-33B257E28539'};
-- @result set to null
SET @result =
(
SELECT MAX(AccountId)
FROM Accounts
WHERE AccountId={guid '7AD4D33C-1ED7-4183-B7F3-48C33D666525'}
);
SELECT @result;
Beachten Sie, dass das Skalaraggregat eine Zeile erzeugt, obwohl es keine Eingabe empfängt.
Dokumentation:
Wenn die SELECT-Anweisung keine Zeilen zurückgibt, behält die Variable ihren aktuellen Wert bei. Wenn expression eine skalare Unterabfrage ist, die keinen Wert zurückgibt, wird die Variable auf NULL gesetzt.
Für die Zuweisung von Variablen empfehlen wir, SET @local_variable anstelle von SELECT @local_variable zu verwenden.
Weitere Lektüre: