Inicio > Base de datos > Cuándo utilizar SET vs SELECT al asignar valores a las variables en SQL Server

Cuándo utilizar SET vs SELECT al asignar valores a las variables en SQL Server

jueves, 25 de enero de 2024 Dejar un comentario Ir a comentarios

SET y SELECT pueden ser usados para asignar valores a las variables a través de T-SQL. Ambos cumplen su tarea, pero en algunos casos se pueden producir resultados inesperados. En este artículo menciono detalles sobre las consideraciones para elegir entre los métodos SET y SELECT al asignar un valor a una variable.

En la mayoría de los casos SET y SELECT pueden ser utilizados alternativamente sin ningún efecto.


Los siguientes son algunos de los escenarios que requieren consideración en la elección entre SET o SELECT. Para mas aclaraciones usaremos scripts para la base de datos AdventureWorks.

Cada script a continuación se compone de parte 1 y parte 2. Sería mejor si ejecutas cada parte de los scripts por separado para que puedas ver los resultados de cada método.

Retornando valores a través de una consulta

Cada vez que es asignando un valor a una variable mediante una consulta, SET aceptará y asignara un escalar (solo) un valor de una consulta. Mientras SELECT podría aceptar múltiples valores devueltos. Pero después de aceptar varios valores a través del comando SELECT no tienes manera de rastrear que valor está en la variable. El último valor devuelto en la lista llenará la variable. Debido a esta situación puede conducir a resultados no esperados, ya que no se genera ningún error o advertencia si varios valores fueron devueltos al usar el SELECT. Así pues, si varios valores se podría esperar utilizar la opción SET con la correcta aplicación de los mecanismos de control de errores.

Para aclarar más el concepto por favor ejecuta el siguiente script #1 en dos partes por separado para ver los resultados

Script #1. Uso de SET para asignar valores

USE AdventureWorks
GO

-- Part1. Populate by single row through SET
DECLARE @Var1ForSet varchar(50)
SET @Var1ForSet = (SELECT [Name] FROM Production.Product WHERE ProductNumber = 'HY-1023-70')
PRINT @Var1ForSet
GO

-- Part 2. Populate by multiple rows through SET
DECLARE @Var2ForSet varchar(50)
SET @Var2ForSet = (SELECT [Name] FROM Production.Product WHERE Color = 'Silver')
PRINT @Var2ForSet
GO

La parte 1 del script tendrá éxito. La variable se rellena con un valor único través de la SET. Pero en la parte 2 del script el siguiente mensaje de error se produce y la instrucción SET dejará de llenar la variable cuando se devuelve más de un valor.

Mensaje de error generado para SET

Msg 512, Level 16, State 1, Line 4
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

Por ello SET previene la asignacion de valores ambiguos.

En caso de SELECT, aunque los valores devueltos por la consulta son varios, no genera error y no ganrá manera de rastrear que varios valores fueron devueltos y que valor está en la variable. Eso se demuestra en el siguiente script:

Script #2. Usar SELECT para asignar valores

USE AdventureWorks
GO

-- Part1. Populate by single row through SELECT
DECLARE @Var1ForSelect varchar(50)
SET @Var1ForSelect = (SELECT [Name] FROM Production.Product WHERE ProductNumber = 'HY-1023-70')
PRINT @Var1ForSelect
GO

-- Part2. Populate by multiple rows through SELECT
DECLARE @Var2ForSelect varchar(50)
SELECT @Var2ForSelect = [Name] FROM Production.Product WHERE Color = 'Silver'
PRINT @Var2ForSelect
GO

Tanto la parte 1 como la parte 2 fueron ejecutadas con éxito. En la parte 2 varios valores se asignaron y aceptaron, sin sabe qué valor realmente se usó. Así cuando se espera la recuperación de varios valores luego de considerar las diferencias de comportamiento entre SET y SELECT e implementar el manejo de errores para estas circunsatancias.

Asignar múltiples valores a múltiples variables

Si tienes que poblar múltiples variables, en lugar de utilizar instrucciones SET por separado cada vez, considera el uso de SELECT para poblar todas las variables en una sola instrucción. Esto puede ser usado para poblar las variables en forma directa o mediante la selección de valores desde la base de datos.

Considera el siguiente script que compara el uso de SELECT y SET:

Script #3. Poblar múltiples variables a través de SELECT

USE AdventureWorks
GO

-- Part 1. Assign direct values to multiple variables
DECLARE @var1 VARCHAR(50)
DECLARE @var2 VARCHAR(50)
DECLARE @var3 VARCHAR(50)

SELECT @var1 = 'Value1', @var2 = 'Value2', @var3 = 'Value3'
PRINT @var1
PRINT @var2
PRINT @var3
GO

-- Part 2. Assign retrieved values to multiple variables
DECLARE @name VARCHAR(50)
DECLARE @productNo VARCHAR(25)
DECLARE @color VARCHAR(15)

SELECT @name = [Name], @productNo = ProductNumber, @color = Color
FROM Production.Product 
WHERE ProductID = 320
PRINT @name
PRINT @productNo
PRINT @color
GO

Si estás usando SET, entonces cada varible debe tener asignado valores individualmente a través de múltiples instrucciones como se muestra a continuación:

Script #4. Poblar múltiples variables a través de SET

USE AdventureWorks
GO

-- Part 1. Assign direct values to multiple variables
DECLARE @var1 VARCHAR(50)
DECLARE @var2 VARCHAR(50)
DECLARE @var3 VARCHAR(50)
SET @var1 = 'Value1'
SET @var2 = 'Value2'
SET @var3 = 'Value3'
PRINT @var1
PRINT @var2
PRINT @var3 
GO

-- Part 2. Assign retrieved values to multiple variables
DECLARE @name VARCHAR(50)
DECLARE @productNo VARCHAR(25)
DECLARE @color VARCHAR(15)
SET @name =(SELECT [Name] FROM Production.Product WHERE ProductID = 320)
SET @productNo = (SELECT ProductNumber FROM Production.Product WHERE ProductID = 320)
SET @color = (SELECT Color FROM Production.Product WHERE ProductID = 320)
PRINT @name
PRINT @productNo
PRINT @color
GO

Obviamente SELECT es mas eficiente que SET mientras asigna valores a múltiples variables en términos de instrucciones ejecutadas, código y bytes de red.

¿Qué si la variable no se pobla con éxito?

Si una variable no es poblada con éxito entonces el comportamiento de SET y SELECT sería diferente. Fallas en la asignación puede ser debido a que ningún resultado es devuelto o cualquier otro valor no compatible con la variable. En este caso, SELECT preservará el valor anterior, si lo hubiere, donde SET retornará NULL. Debido a la diferente funcionalidad, ambos pueden conducir a resultados inesperados y se deben considerar con cuidado.

Esto se demuestra en el siguiente script:

Script# 5. Comportamiento de SET y SELECT para valor faltante

USE AdventureWorks
GO -- Part 1. Observe behavior of missing result with SET
DECLARE @var1 VARCHAR(20)
SET @var1 = 'Value 1 Assigned'
PRINT @var1
SET @var1 = (SELECT Color FROM Production.Product WHERE ProductID = 32022)
PRINT @var1
GO
-- Part 1. Observe behavior of missing result with SELECT
DECLARE @var1 VARCHAR(20)
SELECT @var1 = 'Value 1 Assigned'
PRINT @var1 
SELECT @var1 = Color FROM Production.Product WHERE ProductID = 32023
PRINT @var1
GO

Podemos observar que la parte 1 genera NULL cuando no devuelve ningun valor para poblar la variable. en cambio la parte 2 produce el valor previo que se conserva despues de la asignacion fallida de la variable. Esta situación puede conducir a resultados inesperados y requiere consideración.

Siguiendo los estandares

Usar SELECT puede parecer la mejor opción para escenarios especificos, pero ten en cuenta que SELECT se usa para asignar valores a las variables no esta incluido en los estandares ANSI. Si sigues los estandares para fines de migracion de código, entonces evita el uso de SELECT y usa SET en su lugar.

Conclusión

Las mejores prácticas no apegarse a un método. Según los escenarios es posible que desee utilizar tanto SET como SELECT.

A continuación se presentan algunos escenarios para usar SET:

  • Si estás obligado a asignar un solo valor directamente a la variable y no hay consulta para buscar el valor.
  • Se esperan asignaciones NULL (retorna NULL en un conjunto de resultados).
  • Los estandares están destinados a pasar cualquier plan de migración.
  • Se esperan resultados no escalares y deben ser manipulados.

Usando SELECT es eficiente y flexible en los siguientes casos:

  • Múltiples variables están siendo pobladas por asignación directa de valores.
  • Múltiples variables están siendo pobladas por una unica fuente (tabla, vista).
  • Menos codigo para asignar multiples variables.
  • Usa esta opción si necesitas @ROWCOUNT y @ERROR de la última sentencia ejecutada.

Comparte y diviertete:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • BarraPunto
  • Bitacoras.com
  • BlinkList
  • Blogosphere
  • Live
  • Meneame
  • MSN Reporter
  • MySpace
  • RSS
  • Suggest to Techmeme via Twitter
  • Technorati
  • LinkedIn
  • email
  • FriendFeed
  • PDF
  • Reddit
  • Wikio IT
  • Add to favorites
  • blogmarks
Top Footer