SQL Server - 嵌套while循环中的全局变量重置

时间:2017-09-18 12:18:47

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

我有一个全局变量,它在嵌套的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

2 个答案:

答案 0 :(得分:1)

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

在解析每个批次时遇到变量声明,变量名称从该点开始变为有效,直到批次结束。

E.g。这有效:

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

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

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

答案 1 :(得分:0)

问题在于您提供的查询,您只查询前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