Everyday I learn something new, it seems :) Can someone please explain to me the rationale behind the following code behavior:
DECLARE @A INT
SET @A = 15
SET @A = (SELECT ValueThatDoesntExist FROM dbo.MyTable WHERE MyColumn = 'notfound')
SELECT @A
-- Rsultset is NULL
SET @A = 15
SELECT @A = ValueThatDoesntExist FROM dbo.MyTable WHERE MyColumn = 'notfound'
SELECT @A
-- Resultset is 15
From what I see, SET changes the value of the variable if the resultset is NULL, while SELECT doesn't. Is this normal ANSI behavior or is it T-SQL specific?
Of, course, if I do SELECT @A = NULL
, the assignment happens correctly.
SET is used to assign a value to a variable and SELECT is used to assign a value or to select value from a variable/table/view etc.
SET and SELECT may be used to assign values to variables through T-SQL. Both fulfill the task, but in some scenarios unexpected results may be produced. In this tip I elaborate on the considerations for choosing between the SET and SELECT methods for assigning a value to variable.
SET is the ANSI standard for variable assignment, SELECT is not. SET can only assign one variable at a time, SELECT can make multiple assignments at once. If assigning from a query, SET can only assign a scalar value. If the query returns multiple values/rows then SET will raise an error.
To assign a value to a variable, use the SET statement. This is the preferred method of assigning a value to a variable. A variable can also have a value assigned by being referenced in the select list of a SELECT statement.
The first version sets A to the result of a query:
SET @A = (SELECT ValueThatDoesntExist FROM dbo.MyTable WHERE MyColumn = 'notfound')
Basically the select
in in scalar context, and if it doesn't find a row, it evaluates to null
.
The second version sets A for each row in the result set:
SELECT @A = ValueThatDoesntExist FROM dbo.MyTable WHERE MyColumn = 'notfound'
Since there are no rows, A is never assigned to. Another example:
declare @a int
select @a = i
from (
select 1
union all select 2
union all select 3
) as SubQueryAlias(i)
order by
i
select @a
This will assign 3 values to @a
. The last one assigned is 3
, so that's what the query prints.
Well the select returns no rows. So practically there is not assignment.
While the set will have a null as a result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With