La semántica de las dos declaraciones es diferente:
- El primero no establece el valor de la variable si no se encuentra ninguna fila.
- El segundo siempre establece la variable, incluso en nulo si no se encuentra ninguna fila.
La exploración constante produce una fila vacía (¡sin columnas!) Que dará como resultado que la variable se actualice en caso de que nada coincida con la tabla base. La unión izquierda asegura que la fila vacía sobreviva a la unión. Se puede pensar que la asignación variable ocurre en el nodo raíz del plan de ejecución.
Utilizando 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;
Utilizando 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;
Planes de ejecucion
No llega ninguna fila al nodo raíz, por lo que no se produce ninguna asignación.
Una fila siempre llega al nodo raíz, por lo que se produce una asignación variable.
La exploración constante adicional y la unión externa izquierda de los bucles anidados no son motivo de preocupación. La unión en particular es barata, ya que se garantiza que encontrará una fila en su entrada externa y, como máximo, una fila (en su ejemplo) en la entrada interna.
Hay otras formas de garantizar que se genere una fila a partir de la subconsulta para garantizar que se produzca una asignación variable. Una es usar un agregado escalar redundante (sin grupo por cláusula):
-- 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;
Observe que el agregado escalar produce una fila a pesar de que no recibe ninguna entrada.
Documentación:
Si la instrucción SELECT no devuelve filas, la variable conserva su valor actual. Si expresión es una subconsulta escalar que no devuelve ningún valor, la variable se establece en NULL.
Para asignar variables, le recomendamos que use SET @local_variable en lugar de SELECT @local_variable.
Otras lecturas: