Semantyka obu instrukcji jest inna:
- Pierwszy nie ustawia wartości zmiennej, jeśli nie znaleziono wiersza.
- Drugi zawsze ustawia zmienną, w tym na null, jeśli nie znaleziono wiersza.
Ciągłe skanowanie tworzy pusty wiersz (bez kolumn!), Co spowoduje aktualizację zmiennej, na wypadek gdyby nic nie pasowało z tabeli podstawowej. Lewe złączenie zapewnia, że pusty wiersz przetrwa złączenie. Przypisanie zmiennej można traktować jako działanie w węźle głównym planu wykonania.
Za pomocą 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;
Za pomocą 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;
Plany wykonania
Żaden wiersz nie dociera do węzła głównego, więc nie następuje przypisanie.
Wiersz zawsze dociera do węzła głównego, więc następuje przypisanie zmiennej.
Dodatkowe stałe skanowanie i zagnieżdżone pętle pozostawione przy zewnętrznym złączeniu nie stanowią powodu do niepokoju. Zwłaszcza połączenie jest tanie, ponieważ gwarantuje napotkanie jednego rzędu na wejściu zewnętrznym i co najwyżej jednego rzędu (w twoim przykładzie) na wejściu wewnętrznym.
Istnieją inne sposoby zapewnienia generowania wiersza z podzapytania w celu zapewnienia przypisania zmiennej. Jednym z nich jest użycie redundantnego agregatu skalarnego (bez grupowania według klauzul):
-- 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;
Zauważ, że agregat skalarny tworzy wiersz, nawet jeśli nie otrzymuje żadnych danych wejściowych.
Dokumentacja:
Jeśli instrukcja SELECT nie zwraca wierszy, zmienna zachowuje swoją bieżącą wartość. Jeśli wyrażenie jest skalarnym podzapytaniem, które nie zwraca żadnej wartości, zmienna jest ustawiona na NULL.
Do przypisywania zmiennych zalecamy użycie SET @ zmienna_lokalna zamiast SELECT @ zmienna_lokalna.
Dalsza lektura: