【问题标题】:How to organize infinite while loop in SQL Server?如何在 SQL Server 中组织无限 while 循环?
【发布时间】:2011-01-28 05:14:51
【问题描述】:

我想在 SQL Server 2005 中使用无限 WHILE 循环,并在特定条件下使用 BREAK 关键字退出。

while true 不起作用,所以我必须使用while 1=1。 有没有更好的方法来组织无限循环?

我知道我可以使用goto,但while 1=1 begin ... end 在结构上看起来更好。

【问题讨论】:

  • 您可以使用“while 0 = 0”。它看起来更加严格和令人讨厌。 :)

标签: sql sql-server sql-server-2005 loops boolean


【解决方案1】:

除了WHILE 1 = 1 正如其他答案所建议的那样,我经常在我的 SQL“infintie”循环中添加一个“超时”,如下例所示:

DECLARE @startTime datetime2(0) = GETDATE();

-- This will loop until BREAK is called, or until a timeout of 45 seconds.
WHILE (GETDATE() < DATEADD(SECOND, 45, @startTime))
BEGIN
    -- Logic goes here: The loop can be broken with the BREAK command.

    -- Throttle the loop for 2 seconds.    
    WAITFOR DELAY '00:00:02';
END

我发现上述技术在从long polling AJAX 后端调用的存储过程中很有用。在数据库端使用循环使应用程序不必不断地访问数据库以检查新数据。

【讨论】:

  • 可能值得注意的是,您不能在函数中使用 WAITFOR。
【解决方案2】:

使用While 1 = 1Break 语句是这样做的方法。 TRUEFALSE 在 T-SQL 中没有常量。

【讨论】:

    【解决方案3】:

    如果你真的必须使用无限循环而不是使用while 1=1,我会这样做。

    这里的问题是,没有其他方法可以避免无限循环吗?这些事情往往会出错;)

    【讨论】:

    • 我同意 WoLpH。为什么不能将中断条件放在 WHILE 语句中?那是更好的方法。设置条件,有 WHILE 语句,然后在循环中再次设置条件是正常的。不要害怕重复的几行代码。不过,我也写了一些 WHILE(TRUE) 语句。
    • @Marcus:重复的代码行是我一直试图避免的。我相信无限循环比重复的代码行更邪恶。
    【解决方案4】:

    你可以使用下面的 sn-p 在 soem 条件上升后踢一个 sp。我假设您使用某种 CurrentJobStatus 表,其中所有作业/sp 都保持其状态...

    -- *** reload data on N Support.usp_OverrideMode with checks on Status
    /* run 
    Support.usp_OverrideMode.Number1.sql
    and
    Support.usp_OverrideMode.Number2.sql
    */
    
    
    DECLARE @FileNameSet TABLE (FileName VARCHAR(255));
    
    INSERT INTO @FileNameSet
    VALUES ('%SomeID1%');
    
    INSERT INTO @FileNameSet
    VALUES ('%SomeID2%');
    
    DECLARE @BatchRunID INT;
    
    DECLARE @CounterSuccess INT = 0;
    DECLARE @CounterError INT = 0;
    
    -- Loop
    WHILE WHILE (@CounterError = 0 AND  @CounterSuccess < (select COUNT(1) c from @FileNameSet) )
    BEGIN
    
    DECLARE @CurrenstStatus VARCHAR(255)
    SELECT @CurrenstStatus = CAST(GETDATE() AS VARCHAR)
    
    
        -- Logic goes here: The loop can be broken with the BREAK command.
        SELECT @CounterSuccess = COUNT(1)
        FROM dbo.CurrentJobStatus t
        INNER JOIN @FileNameSet fns
            ON (t.FileName LIKE fns.FileName) 
        WHERE LoadStatus = 'Completed Successfully'
    
        SELECT @CounterError = COUNT(1)
        FROM dbo.CurrentJobStatus t
        INNER JOIN @FileNameSet fns
            ON (t.FileName LIKE fns.FileName) 
        WHERE LoadStatus = 'Completed with Error(s)'
    
        -- Throttle the loop for 3 seconds.    
        WAITFOR DELAY '00:00:03';
    
        select @CurrenstStatus = @CurrenstStatus +char(9)+ '@CounterSuccess ' + CAST(@CounterSuccess AS VARCHAR(11)) 
     +  char(9)+ 'CounterError ' + CAST(@CounterError AS VARCHAR(11)) 
    
        RAISERROR (
                'Looping... @ %s'
                ,0
                ,1
                ,@CurrenstStatus
                )
        WITH NOWAIT;
    
    END
    -- TODO add some codition on @CounterError value
            /* run 
    Support.usp_OverrideMode.WhenAllSuceed.sql
    */
    

    请注意,代码是灵活的,您可以在 @FileNameSet 表 var 上添加尽可能多的条件检查 马里奥

    【讨论】:

      猜你喜欢
      • 2010-12-19
      • 2020-03-01
      • 2014-03-29
      • 2015-06-25
      • 2018-10-28
      • 2012-12-24
      • 1970-01-01
      • 2011-11-29
      • 2013-08-18
      相关资源
      最近更新 更多