I always had this doubt, but I never researched and even this happens a lot to me. No Stackoverflow in English has this topic explaining when to use one and the other, the main differences are:
SET is ansi standard for variable assignment, SELECT is not.
SET can only assign one variable at a time, SELECT can do several
assignments at the same time.
- If assigned from a query,
SET can only assign a value
scale. If the query returns multiple values/lines then SET
an error may occur. SELECT shall assign one of the values to the variable and
will hide the fact that several values have been returned (then,
probably would never know why something was wrong in another
place)
- When assigning from a query if there is no value
returned the
SET assign NULL, where SELECT will not make the assignment
(therefore, the variable will not be changed from its previous value). See code below
- With regard to differences in performance there are no differences
direct between
SET and SELECT. To SELECT ability to
do various assignments in a single action gives a slight advantage
of performance on SET.
Translating into item 3 code:
Take a test yourself through the code below.
declare @var varchar(20)
set @var = 'Joe'
set @var = (select Campo from SuaTabela)
select @var
select @var = Campo from SuaTabela
select @var
The first code will return the following error message:
Subquery returned more than 1 value. This is not permitted when the
subquery Follows =, != , <, <= , >, >= or when the subquery is used as
an Expression.
The second will return you a value.
Translating into code item 4:
declare @var varchar(20)
set @var = 'Joe'
set @var = (select name from master.sys.tables where name = 'qwerty')
select @var /* @var Agora é null */
--SAÍDA NULL
set @var = 'Joe'
select @var = name from master.sys.tables where name = 'qwerty' -- AQUI NÃO É ATRIBUÍDO NULL
select @var
--SAÍDA Joe
It is quite common to use in the system where I work SELECT in FUNCTIONS to concatenate comma-separated values instead of displaying one per line.
In practice
Imagine that I wish to know all the emails of your customers and these should come separated by comma in a single result.
One FUNCTION that would solve your problem will be something like:
CREATE FUNCTION [dbo].[fncEmails](@IDCliente int)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @RETORNO VARCHAR(MAX)
SELECT @retorno = COALESCE(@retorno + ', ', '') + Email
FROM Clientes
RETURN @retorno
END
Upshot:
'[email protected], [email protected], [email protected]'
I didn’t even know that the ANSI standard provided setting values of variables! I thought ANSI was purely declarative
– Jefferson Quesado