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