在存储过程中的 while 块内定义的变量范围 - SQl Server

发布于 2024-11-08 16:48:43 字数 870 浏览 0 评论 0原文

我在存储过程中遇到了一个有趣的场景(至少对我来说)。想请教专家对此的意见和想法。

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

我期望这个块会给出如下输出

<前><代码>值_10_ 价值_ _ 值_8_ 价值_ _ 值_6_ 价值_ _ 值_4_ 价值_ _ 值_2_ 价值_ _

相反,我得到的输出如下:

值_10_

值_10_

值_8_

值_8_

值_6_

值_6_

值_4_

值_4_

值_2_

值_2_

我想如果我在 while 块内声明一个变量,那么对于每次迭代,它都会将该值重置为 NULL 或默认值(来自 c# 背景)。

如果这是设计使然,那么我的问题是 SQLServer 如何处理 while 块内该变量的“DECLARE”语句?由于变量已经在内存中,它会忽略它吗?

有人可以向我解释一下这种行为吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

謌踐踏愛綪 2024-11-15 16:48:43

变量范围是整个批处理,在本例中是一个存储过程。

它不会重新声明每个循环

所以这完全符合预期

编辑:

最近有一个 博客文章非常相似。作者很快就纠正了:-)

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 :-)

转角预定愛 2024-11-15 16:48:43

来自 Transact-SQL 变量

变量的范围是 Transact-SQL 语句的范围
可以引用该变量。变量的作用域从
点它被声明直到批处理或存储过程结束
它是这样声明的。

DECLARE 本身并不是可执行语句。变量声明都是在编译时识别的,并在执行上下文中为它们保留内存。

如果您使用 2008+ Declare 和 Set 语法。然而,语句的 Set 部分出现在每次循环迭代中。

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

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
何止钟意 2024-11-15 16:48:43

尝试一下这个有趣的

if 1 = 0
begin
  -- will never happen
  declare @xx int
end  
else  
begin
  set @xx = 1
end  
print @xx

显然声明代码不必执行。仅在使用前声明。

这不起作用

if 1 = 0
begin
  -- will never happen
  set @xx = 1
end  
else  
begin
  declare @xx int
end  
print @xx

Try this for fun

if 1 = 0
begin
  -- will never happen
  declare @xx int
end  
else  
begin
  set @xx = 1
end  
print @xx

Apparently the declare code does not have to be executed. Only be declared before it is used.

This don't work

if 1 = 0
begin
  -- will never happen
  set @xx = 1
end  
else  
begin
  declare @xx int
end  
print @xx
泛滥成性 2024-11-15 16:48:43

声明

局部变量的作用域是声明它的批处理。

T-SQL 中不再有“本地”作用域规则。这也意味着您不能在 IF 和 ELSE 块内声明相同的变量名。

Declare 所做的只是声明一个变量。它与赋值无关。任何从未被赋值的变量的值为NULL。但此后,变量值再次变为 NULL 的唯一方法是通过显式赋值。

因此,如果您需要在每次循环迭代的顶部将其设置为 NULL,则必须显式分配它。

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.

白芷 2024-11-15 16:48:43

在 T-SQL 中,WHILE..END 没有单独的作用域,例如,您可以在 WHILE之后 SELECT @insidevalue结束

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

千纸鹤带着心事 2024-11-15 16:48:43
 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
 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
盗琴音 2024-11-15 16:48:43
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
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
就是爱搞怪 2024-11-15 16:48:43

整数数据类型通常没有 NULL,只有 0 的

Declare 语句不会每次在循环内发生,

为什么不直接使用

DECLARE @loopcounter INT
SET @loopcounter=10
WHILE @loopcounter > 0
BEGIN
  IF @loopcounter%2 = 0
  PRINT 'Value_' + CAST(@loopcounter AS NVARCHAR) + '_'
  else
  PRINT 'Value_ _'
  SET @loopcounter = @loopcounter - 1
END

这给出:

Value_10_
Value_ _
Value_8_
Value_ _
Value_6_
Value_ _
Value_4_
Value_ _
Value_2_
Value_ _

Integer data types often don't have NULL's only 0's

Declare statement won't happen each time within the loop

why don't you just use

DECLARE @loopcounter INT
SET @loopcounter=10
WHILE @loopcounter > 0
BEGIN
  IF @loopcounter%2 = 0
  PRINT 'Value_' + CAST(@loopcounter AS NVARCHAR) + '_'
  else
  PRINT 'Value_ _'
  SET @loopcounter = @loopcounter - 1
END

That gives:

Value_10_
Value_ _
Value_8_
Value_ _
Value_6_
Value_ _
Value_4_
Value_ _
Value_2_
Value_ _
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文