web-dev-qa-db-ja.com

SQL Serverで無限のwhileループを整理するにはどうすればよいですか?

SQL Server2005で無限のWHILEループを使用し、BREAKキーワードを使用して特定の条件でループを終了したいと思います。

while trueが機能しないため、while 1=1を使用する必要があります。無限ループを整理するためのより良い方法はありますか?

gotoを使用できることは知っていますが、while 1=1 begin ... endは構造的に見栄えがします。

17
alpav

他の回答が示唆するようにWHILE 1 = 1に加えて、次の例のように、SQLの「無限」ループに「タイムアウト」を追加することがよくあります。

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 バックエンドから呼び出されるストアドプロシージャ内で役立つことがわかりました。データベース側にループがあると、アプリケーションは常にデータベースにアクセスして新しいデータをチェックする必要がなくなります。

25
Daniel Vassallo

While 1 = 1Breakステートメントとともに使用するのがその方法です。 T-SQLには、[〜#〜] true [〜#〜]または[〜#〜] false [〜#〜]の定数はありません。

14
Thomas

while 1=1を使用するよりも、本当に無限ループを使用する必要がある場合は、私が行う方法です。

ここでの問題は、無限ループを回避する他の方法はないかということです。これらのことはうまくいかない傾向があります;)

2
Wolph

以下のスニペットを使用して、soem条件が発生した後にspをキックできます。私はあなたがすべてのjobs/spがそれらのステータスを保持するある種のCurrentJobStatusテーブルを持っていると仮定します...

-- *** 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テーブルに条件チェックをいくつでも追加できますvarMario

0
rio