2010-03-16 14 views
14

Ich möchte unendliche WHILE Schleife in SQL Server 2005 verwenden und BREAK Schlüsselwort verwenden, um es unter bestimmten Bedingungen zu beenden.Wie zu organisieren unendliche While-Schleife in SQL Server?

while true funktioniert nicht, also muss ich while 1=1 verwenden. Gibt es eine bessere Möglichkeit, Endlosschleife zu organisieren?

Ich weiß, dass ich goto verwenden kann, aber while 1=1 begin ... end sieht strukturell besser aus.

+0

Sie können "while 0 = 0" verwenden. Es sieht strenger und geeky aus. :) –

Antwort

20

Neben dem WHILE 1 = 1 wie die anderen Antworten vorschlagen, füge ich oft ein „Timeout“ zu meinen SQL „infintie“ Schleifen, wie im folgenden Beispiel:

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 

Ich fand die obige Technik in einer gespeicherten Prozedur nützlich, die von einem long polling AJAX-Back-End aufgerufen wird. Durch die Schleife auf der Datenbankseite wird die Anwendung davon befreit, ständig auf die Datenbank zu stoßen, um nach neuen Daten zu suchen.

+0

Vielleicht ist es erwähnenswert, dass Sie WAITFOR nicht in einer Funktion verwenden können. –

10

Mit While 1 = 1 mit einer Break Anweisung ist der Weg, es zu tun. Es gibt keine Konstante in T-SQL für TRUE oder FALSE.

2

Wenn Sie wirklich eine Endlosschleife als while 1=1 verwenden müssen, ist die Art, wie ich es tun würde.

Die Frage ist, gibt es keine andere Möglichkeit, eine Endlosschleife zu vermeiden? Diese Dinge sind in der Regel nur schief gehen;)

+0

Ich stimme WoLpH zu. Warum können Sie die Abbruchbedingung nicht in die WHILE-Anweisung einfügen? Das ist der bessere Weg. Es ist normal, die Bedingung einzurichten, die WHILE-Anweisung zu verwenden und die Bedingung erneut in der Schleife einzurichten. Haben Sie keine Angst vor ein paar doppelten Codezeilen. Obwohl ich auch einige WHILE (TRUE) Statements geschrieben habe. –

+2

@Marcus: Doppelte Codezeilen versuche ich immer zu vermeiden. Ich glaube, Endlosschleife ist weniger böse als doppelte Codezeilen. – alpav

0

Sie könnten das folgende Snippet verwenden, um eine SP zu starten, nachdem die Soem-Bedingung erhöht wurde. Ich gehe davon aus, dass Sie irgendeine Art von CurrentJobStatus Tabelle ahev wo alle Aufträge/sp ihren Status flexibile hält ...

-- *** 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 
*/ 

Hinweis der Code Sie so viele Bedingungsprüfungen auf der @FileNameSet Tabelle var Mario hinzufügen