【问题标题】:SQL Server - Global Variable Resets in Nested While LoopSQL Server - 嵌套 While 循环中的全局变量重置
【发布时间】:2018-02-26 23:32:36
【问题描述】:

我有一个全局变量,它在嵌套的 While 循环中增加。在每次迭代中,它会将值重置为 1(即初始初始化值)。

示例可重现代码:

SET NOCOUNT ON;
DECLARE @GlobalCounter INT = 1;
DECLARE @CounterOne INT = 1;
DECLARE @CounterTwo INT = 1;

WHILE(@CounterOne <= 10)
BEGIN
    PRINT 'Outer Loop:';
    PRINT @GlobalCounter;

    DECLARE @SerialInfo table
    (
        [Id] [int] IDENTITY(1,1) NOT NULL,
        [SNumber] [NVARCHAR](20) NOT NULL,
        PRIMARY KEY ([Id])
    );

    SET @CounterTwo = 1;
    WHILE(@CounterTwo <= 10)
    BEGIN

        DECLARE @SerialNumber NVARCHAR(20);
        SET @SerialNumber = 'SRL: ' + CONVERT(NVARCHAR(10), @GlobalCounter);

        INSERT INTO @SerialInfo([SNumber]) VALUES (@SerialNumber);

        SET @GlobalCounter = @GlobalCounter + 1;
        SET @CounterTwo = @CounterTwo + 1;
    END

    SET @CounterTwo = 1;
    WHILE(@CounterTwo <= 10)
    BEGIN
        SET @SerialNumber = '';
        SELECT @SerialNumber = [SNumber] FROM @SerialInfo WHERE [Id] = @CounterTwo;
        PRINT @SerialNumber;
        SET @CounterTwo = @CounterTwo + 1;
    END

    SET @CounterOne = @CounterOne + 1;
END

请在全局变量范围及其价值方面帮助我。如何达到预期效果

SRL: 1
SRL: 2
SRL: 3
.
.
.
SRL: 99
SRL: 100

Resultant Image

【问题讨论】:

  • 你目前得到了什么结果?
  • 当我查看@serialinfo 中的结果时不确定问题出在哪里,我得到了您发布的预期结果。我们需要知道你得到了什么结果。
  • @Jonathan 我添加了一个屏幕截图,其中包含上述 SQL 查询的结果。
  • 问题不在于全局计数器——而是表变量的声明。如果您在循环之后执行select * from @SerialInfo,您应该会看到问题。如果您可以描述总体目标,我认为这是提议的解决方案的部分,那么可能有更好的方法可以在没有循环或表变量的情况下完成整个工作。

标签: sql sql-server while-loop scope sql-server-2016


【解决方案1】:

问题在于您提供的查询,您只查询前 10 个 [SNumber]

WHILE(@CounterTwo <= 10)
BEGIN
    SET @SerialNumber = '';
    SELECT @SerialNumber = [SNumber] FROM @SerialInfo WHERE [Id] = @CounterTwo;

检查该查询是否符合您的业务逻辑:

SET NOCOUNT ON;
DECLARE @GlobalCounter = 1;
DECLARE @CounterOne INT = 1;
DECLARE @CounterTwo INT = 1;

WHILE(@CounterOne <= 10)
BEGIN
    DECLARE @SerialInfo table
    (
        [Id] [int] IDENTITY(1,1) NOT NULL,
        [SNumber] [NVARCHAR](20) NOT NULL,
        PRIMARY KEY ([Id])
    );

    SET @CounterTwo = 1;
    WHILE(@CounterTwo <= 10)
    BEGIN

        DECLARE @SerialNumber NVARCHAR(20);
        SET @SerialNumber = 'SRL: ' + cast(@globalCounter as varchar)

        INSERT INTO @SerialInfo([SNumber]) VALUES (@SerialNumber);
        SET @GlobalCounter = @GlobalCounter + 1;
        SET @CounterTwo = @CounterTwo + 1;
    END
    SET @CounterOne = @CounterOne + 1;
END
set @CounterTwo = 1
WHILE(@CounterTwo <= @GlobalCounter)
BEGIN
    SET @SerialNumber = '';
    SELECT @SerialNumber = [SNumber] FROM @SerialInfo WHERE [Id] = @CounterTwo;
    PRINT @SerialNumber;
    SET @CounterTwo = @CounterTwo + 1;
END

【讨论】:

  • 一点也不。 “@SerialInfo”表变量始终包含 10 条记录。
【解决方案2】:

在 T-SQL 中,变量声明参与控制流。因此,仅仅因为 declare @SerialInfo table... 出现在循环内,这并不意味着 @SerialInfo 在每次循环中都重新初始化为空表。

在解析每个批次时,一旦遇到变量声明,变量名就会从该点开始生效,直到批次结束。

例如这行得通:

if 1=0
begin
    declare @a int
end
set @a = 15
print @a

不幸的是,您当前的代码在程序上非常基于,因此很难看到您正在尝试完成什么实际任务并提出修复它的建议。但它可能不需要循环并依赖生成的IDENTITY 值。


希望,从上面可以清楚地看到您所看到的 - @SerialInfo 最终包含 100 行,其中包含您显然想要的所有值。但由于您的print 循环仅查询表的前 10 行,它会继续输出外循环第一次运行时插入的 10 行。

【讨论】:

    猜你喜欢
    • 2016-11-15
    • 1970-01-01
    • 2016-03-15
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 2021-07-31
    • 1970-01-01
    相关资源
    最近更新 更多