2010-03-16 19 views
14

Quiero usar el ciclo infinito WHILE en SQL Server 2005 y usar la palabra clave BREAK para salir de él en ciertas condiciones.¿Cómo organizar el bucle while infinito en SQL Server?

while true no funciona, entonces tengo que usar while 1=1. ¿Hay una mejor manera de organizar el bucle infinito?

Sé que puedo usar goto, pero while 1=1 begin ... end se ve mejor estructuralmente.

+0

Puede usar "while 0 = 0". Se ve más estricto y geek. :) –

Respuesta

20

Además del WHILE 1 = 1 como las otras respuestas sugieren que, a menudo añaden un "tiempo de espera" a mi SQL "infintie" loops, como en el siguiente ejemplo:

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 

Encontré la técnica anterior útil en un procedimiento almacenado que se llama desde un backend long polling AJAX. Tener el bucle en el lado de la base de datos libera a la aplicación de tener que golpear constantemente la base de datos para verificar si hay datos nuevos.

+0

Puede valer la pena señalar que no puede usar WAITFOR en una función. –

10

El uso de While 1 = 1 con una declaración Break es la manera de hacerlo. No hay una constante en T-SQL para TRUE o FALSE.

2

Si realmente tiene que usar un bucle infinito que usar while 1=1 es la manera en que lo haría.

La pregunta aquí es, ¿no hay alguna otra forma de evitar un ciclo infinito? Estas cosas sólo tienden a ir mal;)

+0

Estoy de acuerdo con WoLpH. ¿Por qué no puedes poner la condición de salto en la instrucción WHILE? Esa es la mejor manera. Es normal configurar la condición, tener la instrucción WHILE y volver a configurar la condición en el ciclo. No tengas miedo de algunas líneas de código duplicadas. Sin embargo, también he escrito unas cuantas declaraciones WHILE (TRUE). –

+2

@Marcus: Duplicar líneas de código es lo que siempre trato de evitar. Creo que el ciclo infinito es un mal menor que las líneas duplicadas de código. – alpav

0

puede usar el siguiente fragmento para patear una sp después de que se eleven las condiciones del soem. Asumo que ahev una especie de mesa de CurrentJobStatus donde todos los puestos de trabajo/sp mantiene su estado ...

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

Nota el código es flexibile puede añadir tantos condición comprueba en la tabla @FileNameSet var Mario