Семантика двох тверджень різна:
- Перший не встановлює значення змінної, якщо не знайдено рядка.
- Другий завжди встановлює змінну, включаючи нульову, якщо не знайдено рядка.
Постійне сканування створює порожній рядок (без стовпців!), Що призведе до оновлення змінної у випадку, якщо з базової таблиці нічого не збігається. Лівий з’єднання гарантує, що порожній рядок пережив приєднання. Змінне призначення можна вважати таким, що відбувається в кореневому вузлі плану виконання.
Використання 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;
Використання 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;
Плани виконання
Жоден рядок не надходить до кореневого вузла, тому присвоєння не відбувається.
Рядок завжди надходить у кореневий вузол, тому відбувається присвоєння змінної.
Про додаткове постійне сканування та вкладені петлі зліва назовні приєднання нічого не турбує. Зокрема, з'єднання дешеве, оскільки на його зовнішньому вході гарантовано зустріти один рядок, і максимум один рядок (у вашому прикладі) на внутрішньому вході.
Існують й інші способи забезпечення рядку, створеного з підзапиту, щоб забезпечити призначення змінної. Перший полягає у використанні надмірного скалярного сукупності (немає групи за умовами):
-- 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;
Зауважте, скалярний сукупність створює рядок, навіть якщо він не отримує введення.
Документація:
Якщо оператор SELECT не повертає жодних рядків, змінна зберігає теперішнє значення. Якщо вираз - скалярний підзапит, який не повертає значення, змінна встановлюється в NULL.
Для призначення змінних рекомендуємо використовувати SET @local_variable замість SELECT @local_variable.
Подальше читання: