El uso de instrucciones SELECT y SET para asignaciones de variables es una práctica común en SQL Server. No presté más atención a la diferencia SELECT vs SET, hasta que me encontré con sorprendentes errores lógicos. En el código de producción usando SELECT sobre SET, se produjeron resultados inesperados. Ambos se utilizan indistintamente para la asignación de variables. Es importante saber cuándo usar SELECT sobre SET y viceversa.
En esta publicación de recetas técnicas, una comprensión de la diferencia entre la instrucción SELECT y SET. Además, recorre varios ejemplos que involucran ambas opciones. Como resultado, esto le ayudará a encontrar buenas prácticas y utilizar la opción apropiada mientras se asigna la variable en su código según sus necesidades.
Puntos para reflexionar - SELECT vs SET
1.SELECT puede asignar valores a múltiples variables en una sola consulta. Mientras que SET se utiliza para la asignación de una sola variable.
2.SET es estándar ANSI, lo que indica que otros RDBMS están utilizando un enfoque similar para la asignación de variables. Como práctica estándar. Considerando que, la instrucción SELECT se utiliza dentro de SQL Server.
3.Un valor de variable será NULL en caso de que la consulta no devuelva nada mientras se usa SET en la asignación de variables. Considerando que, SELECT ignorará el resultado de la consulta manteniendo el valor de la variable sin cambios.
4.La instrucción SET falla si la consulta devuelve varias filas. En el caso de SELECT, asigna arbitrariamente / último valor a la variable ignorando las consecuencias.
Repasemos varios ejemplos para comprender la diferencia entre estas dos opciones. Esto le ayudará a tomar una decisión basada en su escenario para utilizar SELECT o SET.
1
Asignación de variable simple o múltiple usando SELECT / SET
Usando SELECT, podemos asignar valores a múltiples variables en una sola declaración. En el siguiente ejemplo, podemos ver que las variables @name y @object_id asignaron valores en una sola línea de código.
--Single vs Multiple value assignment using SEELCT/ SET DECLARE @name as VARCHAR(255) ,@object_id as INT select @name = name, @object_id = object_id from master.sys.all_objects where name = 'spt_values'; --Using SELECT PRINT 'SEELCT - @name - ' + @name; PRINT 'SEELCT - @object_id - ' + CAST(@object_id as VARCHAR(10)); GO
La asignación de variable usando una instrucción SET espera que mencionemos cada nombre de variable individualmente. No se permite el uso de SET para asignaciones de variables múltiples. Por lo tanto, en el siguiente ejemplo, estamos usando dos opciones SET.
DECLARE @name as VARCHAR(255) ,@object_id as INT --Using SET for individual variable assignment SET @name = (SELECT name from master.sys.all_objects where name = 'spt_values'); SET @object_id = (SELECT object_id from master.sys.all_objects where name = 'spt_values'); --Using SELECT PRINT 'SEELCT - @name - ' + @name; PRINT 'SEELCT - @object_id - ' + CAST(@object_id as VARCHAR(10));
2.
Salida NULL - SELECT vs SET - Valor de retorno
En el siguiente ejemplo, la instrucción SELECT usa los valores predeterminados asignados a las variables aunque la consulta no haya devuelto ningún resultado.
Asignar @name = 'Prueba' y @object_id = 1000 como valores predeterminados. Más tarde, al intentar sobrescribir estos valores, sin embargo, la consulta no devuelve ningún resultado, por lo que las variables no se sobrescriben. Aunque la instrucción SELECT conserva los valores predeterminados.
--Default values DECLARE @name as VARCHAR(255) = 'Test' ,@object_id as INT = 1000 --No query output, thus variables are not assigned any values select @name = name, @object_id = object_id from master.sys.all_objects where name = 'NOT_A_Table'; --Using SELECT, returns the old values instead of NULL. SELECT 'SEELCT - @name - ' + @name as [@Name]; SELECT 'SEELCT - @object_id - ' + CAST(@object_id as VARCHAR(10)) as [@ObjectId]; GO
Aquí, en el siguiente ejemplo, se sobrescriben los valores predeterminados. Porque la consulta no devuelve ningún resultado, por lo tanto La sentencia SET asigna NULL a las variables @name y @object_id.
--Default variable values DECLARE @name as VARCHAR(255) = 'Test' ,@object_id as INT = 1000 --Using SET for individual variable assignment SET @name = (SELECT name from master.sys.all_objects where name = 'NOT_A_Table'); SET @object_id = (SELECT object_id from master.sys.all_objects where name = 'NOT_A_Table'); --Using SELECT, returns NULL values instead of default values SELECT 'SEELCT - @name - ' + @name as [@Name]; SELECT 'SEELCT - @object_id - ' + CAST(@object_id as VARCHAR(10)) as [@ObjectId]; GO
3.
SET vs SELECT - Salida de varias filas
El siguiente ejemplo demuestra el comportamiento de una instrucción SELECT si la consulta devuelve varias filas y las utiliza para la asignación de variables. Si ejecuta lo siguiente, la subconsulta devuelve 3 filas como salida.
Select name, object_id from master.sys.all_objects where name IN ('spt_values', 'databases', 'sysservers');
Usar SELECT para asignar valores a variables cuando una consulta devuelve múltiples filas usa último valor devuelto. Con SELECT, los valores de las variables se completan sin mostrar advertencias ni errores. Tenga cuidado con este escenario ya que pueden impactar lógicamente el código si estas variables se utilizan para futuras referencias.
--Default values DECLARE @name as VARCHAR(255) = 'Test' ,@object_id as INT = 1000 --Actual 3 rows are returned SELECT name, object_id from master.sys.all_objects where name IN ('spt_values', 'databases', 'sysservers'); --3 rows are returns, SELECT assigns last value to variables select @name = name, @object_id = object_id from master.sys.all_objects where name IN ('spt_values', 'databases', 'sysservers'); --Using SELECT, returns the last values without any warning/error SELECT 'SEELCT - @name - ' + @name as [@Name]; SELECT 'SEELCT - @object_id - ' + CAST(@object_id as VARCHAR(10)) as [@ObjectId]; GO
Considerando que, la instrucción SET devuelve un error que indica que la subconsulta ha devuelto más de 1 fila por lo tanto, no puede asignar ningún valor aleatorio a las variables.
--Default variable values DECLARE @name as VARCHAR(255) = 'Test' ,@object_id as INT = 1000 --3 rows are returns, SET generates an error SET @name = (SELECT name from master.sys.all_objects where name IN ('spt_values', 'databases', 'sysservers')); SET @object_id = (SELECT object_id from master.sys.all_objects where name IN ('spt_values', 'databases', 'sysservers')); --Error SELECT 'SEELCT - @name - ' + @name as [@Name]; SELECT 'SEELCT - @object_id - ' + CAST(@object_id as VARCHAR(10)) as [@ObjectId]; GO
Error
Msg 512, nivel 16, estado 1, línea 6
La subconsulta devolvió más de 1 valor. Esto no está permitido cuando la subconsulta sigue a =,! =,,> = O cuando la subconsulta se usa como expresión.
Resumen
En resumen, hemos visto la diferencia entre la instrucción SELECT y SET. Usar SELECT con múltiples asignaciones de variables, mientras que SET no lo permite. SELECT no devuelve ningún resultado NULL en caso de que la consulta no devuelva ningún resultado. Pero la opción SET asigna NULL a una variable. Cuando se devuelven varias filas, SELECT asigna aleatoriamente el último valor a una variable, mientras que la instrucción SET falla debido a que la subconsulta devolvió un error de más de 1 fila. Si le gusta esta publicación, puede leer los archivos de la base de datos de recetas técnicas para obtener más información útil.
Descubre más contenido