Как организовать бесконечный цикл в SQL Server? - PullRequest
16 голосов
/ 16 марта 2010

Я хочу использовать бесконечный цикл WHILE в SQL Server 2005 и использовать ключевое слово BREAK для выхода из него при определенных условиях.

while true не работает, поэтому я должен использовать while 1=1. Есть ли лучший способ организовать бесконечный цикл?

Я знаю, что могу использовать goto, но while 1=1 begin ... end выглядит лучше структурно.

Ответы [ 4 ]

22 голосов
/ 16 марта 2010

В дополнение к WHILE 1 = 1, как предлагают другие ответы, я часто добавляю "timeout" в свои циклы 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

Я нашел вышеописанную технику полезной в хранимой процедуре, которая вызывается из длинного бэкэнда AJAX длинного опроса . Наличие цикла на стороне базы данных освобождает приложение от необходимости постоянно обращаться к базе данных, чтобы проверить наличие свежих данных.

11 голосов
/ 16 марта 2010

Использование While 1 = 1 с оператором Break - это способ сделать это. В T-SQL нет константы для TRUE или FALSE .

2 голосов
/ 16 марта 2010

Если вам действительно нужно использовать бесконечный цикл, чем использовать while 1=1, я бы это сделал.

Вопрос здесь в том, не существует ли другого способа избежать бесконечного цикла?Эти вещи, как правило, идут не так;)

0 голосов
/ 17 января 2014

Вы можете использовать фрагмент ниже, чтобы ударить 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 Mario

...