SQL Server: SET x SELECT
Uma dúvida comum está relacionada ao uso do SET e SELECT para atribuição de variáveis.
A partir da versão 7.0 o SQL possui a instrução SET. Seguindo o Padrão ANSI.
Mostrarei algumas diferenças entre o SET e o SELECT para que você possa escolher o comando ideal para cada cenário.
Vamos Criar o ambiente:
Create Table TesteSetSelect
(
Codigo int,
Nome varchar(20)
)
INSERT INTO TesteSetSelect VALUES(1,'João'),(2,'Carlos'),(3,'Maria')
Vamos declarar uma variável usando o SET e atribuir um valor:
Declare @NomeSet varchar(20)
SET @NomeSet=(Select Nome from TesteSetSelect where Codigo=2)
Select @NomeSet
Funcionou normalmente, agora vamos inserir um registro:
INSERT INTO TesteSetSelect VALUES(2,'José')
Compare este dois comandos:
Declare @NomeSet varchar(20)
SET @NomeSet=(Select Nome from TesteSetSelect where Codigo=2)
Select @NomeSet
Declare @NomeSelect varchar(20)
Select @NomeSelect=Nome from TesteSetSelect where Codigo=2
Select @NomeSelect
DIFERENÇA 1:
-O SET não permite uma subconsulta com vários registros.(retorna erro)
-O Select permite, porém só traz o último registro.
Assim, é melhor usar o SET e refinar a sua consulta, ao invés de receber o ultimo valor de uma consulta.
DIFERENÇA 2:
-O SET só permite uma atribuição por comando.
-O Select permite múltiplas atribuições.
Exemplo:
Declare @Codigo int, @Nome varchar(25)
SET @Codigo=1
SET @Nome='José'
SELECT @Codigo=1, @Nome='José'
Num cenário onde você atribui várias variáveis dentro de um loop, melhor utilizar o SELECT pois terá melhor performance.
DIFERENÇA 3:
-O SET retorna NULL caso não encontre um novo valor.
-O SELECT retorna o antigo valor caso não encontre um novo valor.
Declare @CodigoSet int, @CodigoSelect int
SET @CodigoSet=1
SET @CodigoSet=(select 2 from Teste where codigo=100)
SELECT @CodigoSelect=1
SELECT @CodigoSelect=2 from Teste where codigo=100
SELECT @CodigoSet as CodigoSet, @CodigoSelect as CodigoSelect
Para evitar perda de valores utilize o SELECT.
DIFERENÇA 4:
Para manipulação de erros no T-SQL sabemos que as variáveis de sistema @@ERROR e @@ROWCOUNT deverão ser capturadas, imediatamente depois de uma sentença de manipulação de dados, caso contrário, estas variáveis de sistema serão resetadas para 0.
Veja exemplo:
DECLARE @Error int, @RowCount int
SELECT Codigo/0 FROM Teste
SET @RowCount = @@ROWCOUNT
SET @Error = @@ERROR
SELECT @Error AS Erro
DECLARE @Error int, @RowCount int
SELECT Codigo/0 FROM Teste
SELECT @RowCount = @@ROWCOUNT, @Error = @@ERROR
SELECT @Error AS Erro
Veja que com o SET o erro retornado foi 0(zero), sendo que o correto seria 8134. Neste cenário utilize o SELECT.
Assim como na maioria dos comandos, temos que analisar o cenário para tomar a melhor decisão. Espero ter esclarecido estes comandos.
Ozimar Henrique