Sintaxis de for-loop en SQL Server

238

¿Cuál es la sintaxis de un forbucle en TSQL?

Macho
fuente
10
SQL es un lenguaje muy diferente en comparación con lo que estás acostumbrado. Se centra en qué , no cómo . Le dice a SQL Server qué resultados desea y deja que descubra cómo producir la respuesta. O, para reformular lo que acabo de decir, no hay un bucle for en SQL.
Damien_The_Unbeliever
55
WHILE @I < 10; SET @I = @I + 1; BEGIN; ...; END? Sin embargo, esto no debe usarse para la mayoría del procesamiento de consultas (pero a veces es necesario para la manipulación imperativa). Muchas de estas instrucciones / sugerencias están disponibles en Google usando la búsqueda "tsql for loop".
77
Evite bucles a favor de JOINs y establezca operaciones.
Finalizado
2
Si no es experto en SQL, no debería considerar usar un bucle. Solo hay unas pocas condiciones en las que se necesita una y la mayoría del resto del tiempo, usar un bucle es el equivalente a empujar su automóvil en lugar de conducirlo. Aprenda a pensar en términos de conjuntos de datos en lugar de recorrer los registros. El bucle es una función de nivel experto, no porque la sintaxis sea difícil, sino porque necesita saber exactamente cuánto daño puede hacer con ella antes de poder usarla.
HLGEM
2
A veces, podría usarse para conjurar rápidamente datos de prueba en una base de datos de prueba que de todos modos solo va a eliminar poco después. En ese caso, usar esto elimina la necesidad de pasar por un programa separado escrito en algo más como C #, y la ingeniería no es una preocupación particularmente importante. De nuevo, solo digo esto en términos de datos de prueba.
Panzercrisis

Respuestas:

210

T-SQL no tiene un FORbucle, tiene un WHILEbucle
MIENTRAS (Transact-SQL)

WHILE Boolean_expression
BEGIN

END
Enjambres
fuente
8
Las UNIONES (y las operaciones de configuración) deberían preferirse a las construcciones en bucle en SQL.
Finalizado
66
No hay límite en el estrés (especialmente para aquellos que son nuevos en SQL), lo que Damien dijo: "SQL es un lenguaje muy diferente en comparación con lo que estás acostumbrado. Está enfocado en qué, no cómo. Le dices a SQL Server qué resultados que desea y deje que
descubra
1
Es interesante notar que la documentación de MS está mal aquí, realmente. MIENTRAS que no toma una expresión booleana, toma un predicado, que además de poder evaluar como VERDADERO o FALSO, también podría ser DESCONOCIDO.
Damien_The_Unbeliever
360

No hay for-loop, solo el while-loop:

DECLARE @i int = 0

WHILE @i < 20
BEGIN
    SET @i = @i + 1
    /* do some work */
END
TcKs
fuente
20
Tenga en cuenta que si tiene la intención de utilizar el índice en el bucle, es posible que desee aumentar lo último en lugar de lo primero, dependiendo de su caso de uso.
jinglesthula
3
También tenga en cuenta que el valor predeterminado para la variable local no es compatible con SQL simple. Por lo tanto, necesita separarse SET @i = 0antes para el bucle.
Nux
1
@Nux: el 0 se establece durante la declaración explícitamente
TcKs
77
Sí, pero eso no funciona en servidores SQL más antiguos (al menos no en 2005).
Nux
Además, debe tenerse en cuenta que generalmente el trabajo se realiza antes de que se incremente el número entero. Muchos bucles for en SQL realmente usan ese número entero en su trabajo (iterando de fila en fila o de resultado a resultado en tablas temporales) y pueden descartarse si el incremento ocurre al comienzo del ciclo en lugar de al final.
CSS
34

Información extra

Solo para agregar, ya que nadie ha publicado una respuesta que incluya cómo iterar realmente a través de un conjunto de datos dentro de un bucle, puede usar las palabras clave OFFSET FETCH .

Uso

DECLARE @i INT = 0;
SELECT @count=  Count(*) FROM {TABLE}

WHILE @i <= @count
BEGIN

    SELECT * FROM {TABLE}
    ORDER BY {COLUMN}
    OFFSET @i ROWS   
    FETCH NEXT 1 ROWS ONLY  

    SET @i = @i + 1;

END
Dan Cundy
fuente
2
Buena alternativa al uso de un cursor.
DanteTheSmith
28

DECLARE @intFlag INT
SET @intFlag = 1
WHILE (@intFlag <=5) 
BEGIN
    PRINT @intFlag
    SET @intFlag = @intFlag + 1
END
GO
cachemir
fuente
13
¡Bienvenido a Stack Overflow! ¿Consideraría agregar alguna narrativa para explicar por qué funciona este código y qué lo convierte en una respuesta a la pregunta? Esto sería muy útil para la persona que hace la pregunta y para cualquier otra persona que se presente.
Andrew Barber
18
Esto se explica por sí mismo.
Edward Olamisan
44
¿Cómo es que esto no se explica por sí mismo? Tenía la misma pregunta, entendí la respuesta de inmediato.
DanteTheSmith
1
¿En qué se diferencia esta respuesta de @TcKs excepto la convención de nomenclatura?
Sushil Jadhav
7

Qué tal esto:

BEGIN
   Do Something
END
GO 10

... por supuesto, podría poner un contador incremental dentro si necesita contar.

i00
fuente
3
'GO 10'? A SQL Server 2008 no le gusta.
Recurso
7

For loop aún no es oficialmente compatible con el servidor SQL. Ya hay una respuesta para lograr las diferentes formas de FOR Loop. Estoy detallando la respuesta sobre formas de lograr diferentes tipos de bucles en el servidor SQL.

En bucle

DECLARE @cnt INT = 0;

WHILE @cnt < 10
BEGIN
   PRINT 'Inside FOR LOOP';
   SET @cnt = @cnt + 1;
END;

PRINT 'Done FOR LOOP';

Si lo sabe, debe completar la primera iteración del bucle de todos modos, entonces puede probar la versión DO..WHILE o REPEAT..UNTIL del servidor SQL.

HACER ... MIENTRAS

DECLARE @X INT=1;

WAY:  --> Here the  DO statement

  PRINT @X;

  SET @X += 1;

IF @X<=10 GOTO WAY;

REPETIR..UNTIL Loop

DECLARE @X INT = 1;

WAY:  -- Here the REPEAT statement

  PRINT @X;

  SET @X += 1;

IFNOT(@X > 10) GOTO WAY;

Referencia

Somnath Muluk
fuente
Esto parece haber sido copiado-pegado-reordenado aquí: stackoverflow.com/a/46363319/8239061
SecretAgentMan
@SecretAgentMan: Ambas respuestas responden preguntas diferentes. Datos adicionales dados en ambas respuestas.
Somnath Muluk
6

La respuesta simple es NO !!.

No hay FORen SQL, pero puede usar WHILEo GOTOpara lograr la forma en FORque funcionará.

MIENTRAS :

DECLARE @a INT = 10

WHILE @a <= 20
BEGIN
    PRINT @a
    SET @a = @a + 1
END

IR :

DECLARE @a INT = 10
a:
PRINT @a
SET @a = @a + 1
IF @a < = 20
BEGIN
    GOTO a
END

Siempre prefiero WHILEa la GOTOdeclaración.

Ragul
fuente
1
Me gusta cómo mencionaste ambas alternativas en lugar de solo 1 como la mayoría de las respuestas
DanteTheSmith
0

Mientras que el ejemplo de bucle en T-SQL que enumera la fecha de inicio a fin del mes actual.

DECLARE @Today DATE= GETDATE() ,
@StartOfMonth DATE ,
@EndOfMonth DATE;

DECLARE @DateList TABLE ( DateLabel VARCHAR(10) );
SET @EndOfMonth = EOMONTH(GETDATE());
SET @StartOfMonth = DATEFROMPARTS(YEAR(@Today), MONTH(@Today), 1);

WHILE @StartOfMonth <= @EndOfMonth
BEGIN
    INSERT  INTO @DateList
    VALUES  ( @StartOfMonth );
    SET @StartOfMonth = DATEADD(DAY, 1, @StartOfMonth);
END;

SELECT  DateLabel
FROM    @DateList;  
Sameer
fuente
0

Pruébalo, aprendelo:

DECLARE @r INT = 5
DECLARE @i INT = 0
DECLARE @F varchar(max) = ''
WHILE @i < @r
BEGIN

    DECLARE @j INT = 0
    DECLARE @o varchar(max) = ''
    WHILE @j < @r - @i - 1
    BEGIN
        SET @o = @o + ' '
        SET @j += 1
    END

    DECLARE @k INT = 0
    WHILE @k < @i + 1
    BEGIN
        SET @o = @o + ' *'  -- '*'
        SET @k += 1
    END
    SET @i += 1
    SET @F = @F + @o + CHAR(13)
END
PRINT @F

Con fecha:

DECLARE @d DATE = '2019-11-01'
WHILE @d < GETDATE()
BEGIN
    PRINT @d
    SET @d = DATEADD(DAY,1,@d)
END
PRINT 'n'
PRINT @d
Mahesh Mitikiri
fuente