Variables scope which are defined within a while b

2019-02-01 18:48发布

I've come across a interesting scenario (at least for me) in a stored procedure. Would like to have experts opinion and thoughts on it.

DECLARE @loopcounter INT
SET @loopcounter=10

WHILE @loopcounter > 0
BEGIN
  DECLARE @insidevalue int

  IF (@loopcounter%2 = 0)
  SET @insidevalue = @loopcounter

  PRINT 'Value_' + CAST(@insidevalue AS NVARCHAR) + '_'

  SET @loopcounter = @loopcounter - 1
END

I was expecting this block will give the output as below

Value_10_

Value_ _

Value_8_

Value_ _

Value_6_

Value_ _

Value_4_

Value_ _

Value_2_

Value_ _

Instead I got output as below:

Value_10_

Value_10_

Value_8_

Value_8_

Value_6_

Value_6_

Value_4_

Value_4_

Value_2_

Value_2_

I thought if I declare a variable inside a while block, then for every iteration it will reset the value to NULL or default value (from c# background).

If this is by design then my question is how does SQLServer treat 'DECLARE' statement for that variable inside while block? Does it ignore it as the variable is already in memory?

Can somebody please explain me this behavior?

7条回答
姐就是有狂的资本
2楼-- · 2019-02-01 19:22

From Transact-SQL Variables

The scope of a variable is the range of Transact-SQL statements that can reference the variable. The scope of a variable lasts from the point it is declared until the end of the batch or stored procedure in which it is declared.

The DECLARE is not in itself an executable statement. The variable declarations are all identified at compile time and the memory reserved for them in the execution context.

If you use the 2008+ Declare and Set syntax. The Set part of the statement will occur every loop iteration however.

DECLARE @loopcounter INT
SET @loopcounter=10

WHILE @loopcounter > 0
BEGIN
  DECLARE @insidevalue INT = NULL

  IF (@loopcounter%2 = 0)
  SET @insidevalue = @loopcounter

  PRINT 'Value_' + CAST(@insidevalue AS NVARCHAR) + '_'

  SET @loopcounter = @loopcounter - 1
END
查看更多
放荡不羁爱自由
3楼-- · 2019-02-01 19:27
 DECLARE @loopcounter INT
 DECLARE @insidevalue int
   SET @loopcounter=10
       WHILE @loopcounter > 0
        BEGIN
          IF (@loopcounter%2 = 0)
          BEGIN
          SET @insidevalue = @loopcounter
          PRINT 'Value_' + CAST(@insidevalue AS NVARCHAR) + '_'
          END
    ELSE
      PRINT 'Value_'+' '+'_'
      SET @loopcounter = @loopcounter - 1
   END
查看更多
聊天终结者
4楼-- · 2019-02-01 19:30

In T-SQL a WHILE..END is not individually scoped, you can for example SELECT @insidevalue after the WHILE's END.

查看更多
Fickle 薄情
5楼-- · 2019-02-01 19:33

From Declare:

The scope of a local variable is the batch in which it is declared.

There are no more "local" scoping rules in T-SQL. It also means that you can't declare the same variable name inside IF and ELSE blocks.

All Declare does is declare a variable. It has no relation to assignment. The value of any variable that has never been assigned to is NULL. But thereafter, the only way the variables value will become NULL again is through an explicit assignment.

If you need it to be NULL at the top of each loop iteration, therefore, you must explicitly assign it.

查看更多
不美不萌又怎样
6楼-- · 2019-02-01 19:34
DECLARE @loopcounter INT
SET @loopcounter=10

WHILE @loopcounter > 0
BEGIN
  DECLARE @insidevalue int
  IF (@loopcounter%2 = 0)
  begin

    set @insidevalue=@loopcounter
    PRINT 'Value_' + CAST(@insidevalue AS NVARCHAR) + '_'
  end
  ELSE

    PRINT 'Value_' + ' ' + '_'
    SET @loopcounter = @loopcounter - 1
END
查看更多
对你真心纯属浪费
7楼-- · 2019-02-01 19:36

The variable scope is the whole batch in this case a stored procedure.

It isn't re-declared every loop

So this is exactly as expected

Edit:

There is a recent blog article which is quite similar. The author was quickly corrected :-)

查看更多
登录 后发表回答