Składnia for-loop w SQL Server


238

Jaka jest składnia forpętli w TSQL?


10
SQL to zupełnie inny język niż ten, do którego jesteś przyzwyczajony. Koncentruje się na czym , a nie jak . Powiedz SQL Serverowi, jakie wyniki chcesz, i pozwól mu dowiedzieć się, jak uzyskać odpowiedź. Lub, aby przeformułować to, co właśnie powiedziałem - w SQL nie ma pętli for.
Damien_The_Unbeliever

5
WHILE @I < 10; SET @I = @I + 1; BEGIN; ...; END? Nie należy tego jednak używać w przypadku większości przetwarzania zapytań (ale czasami jest to wymagane w przypadku manipulacji imperatywnej). Wiele takich instrukcji / wskazówek jest dostępnych w Google przy użyciu wyszukiwania „tsql for loop”.

7
Unikaj pętli na rzecz JOIN i ustaw operacje.
Oded

2
Jeśli nie jesteś ekspertem w SQL, nie powinieneś rozważać używania pętli. Jest tylko kilka warunków, w których jeden jest potrzebny i przez resztę czasu używanie pętli jest równoważne z pchaniem samochodu zamiast z nim prowadzeniem. Naucz się myśleć w kategoriach zestawów danych zamiast zapętlać rekordy. Pętla jest funkcją na poziomie eksperckim nie dlatego, że składnia jest trudna, ale dlatego, że musisz dokładnie wiedzieć, ile szkód możesz z nią zrobić, zanim będziesz mógł jej używać.
HLGEM,

2
Czasami można go użyć do szybkiego wyczarowania danych testowych w testowej bazie danych, którą i tak wkrótce usuniesz. W takim przypadku użycie tego eliminuje potrzebę przejścia przez osobny program napisany w czymś takim jak C #, a inżynieria nie jest szczególnie poważnym problemem. Znowu mówię to tylko w odniesieniu do danych testowych.
Panzercrisis,

Odpowiedzi:


210

T-SQL nie ma FORpętli, ma WHILEpętlę
WHILE (Transact-SQL)

WHILE Boolean_expression
BEGIN

END

8
ŁĄCZENIA (i ustawiania operacji) powinny być preferowane nad konstrukcjami zapętlonymi w SQL.
Oded

6
Nie ma ograniczeń w stresowaniu (szczególnie dla tych, którzy są nowi w SQL), co powiedział Damien: „SQL jest bardzo innym językiem w porównaniu do tego, do czego jesteś przyzwyczajony. Skupia się na czym, a nie jak. Mówisz SQL Serverowi, co wyniki, które chcesz, i pozwól mu dowiedzieć się, jak uzyskać odpowiedź. ”
ypercubeᵀᴹ

1
Naprawdę ciekawe jest, że dokumentacja MS jest tutaj błędna. PODCZAS nie przyjmuje wyrażenia logicznego - wymaga predykatu - który oprócz możliwości oceny na PRAWDA lub FAŁSZ, może być również NIEZNANY.
Damien_The_Unbeliever

360

Nie ma pętli for, tylko pętla while:

DECLARE @i int = 0

WHILE @i < 20
BEGIN
    SET @i = @i + 1
    /* do some work */
END

20
Należy zauważyć, że jeśli zamierzasz używać indeksu w pętli, możesz chcieć zwiększyć ostatnią rzecz zamiast pierwszej, w zależności od przypadku użycia.
jinglesthula

3
Należy również pamiętać, że domyślna wartość zmiennej lokalnej nie jest obsługiwana w zwykłym SQL. Dlatego SET @i = 0przedtem potrzebujesz osobnej pętli.
Nux

1
@Nux: 0 jest ustawiane podczas deklaracji jawnie
TcKs

7
Tak, ale to nie działa na starszych serwerach SQL (przynajmniej nie w 2005 roku).
Nux

Należy również zauważyć, że generalnie praca jest wykonywana przed zwiększeniem liczby całkowitej. Wiele pętli w SQL faktycznie używa tej liczby całkowitej w swojej pracy (iteracja od wiersza do wiersza lub wynik w tabelach temp) i może zostać odrzucona, jeśli przyrost nastąpi na początku cyklu, a nie na końcu.
CSS

34

Informacje dodatkowe

Aby dodać, ponieważ nikt nie opublikował odpowiedzi, która zawiera sposób iteracji w zbiorze danych wewnątrz pętli, można użyć słów kluczowych OFFSET FETCH .

Stosowanie

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

2
Dobra alternatywa dla używania kursora.
DanteTheSmith

28

DECLARE @intFlag INT
SET @intFlag = 1
WHILE (@intFlag <=5) 
BEGIN
    PRINT @intFlag
    SET @intFlag = @intFlag + 1
END
GO

13
Witamy w Stack Overflow! Czy zastanowiłbyś się nad dodaniem narracji wyjaśniającej, dlaczego ten kod działa i co czyni go odpowiedzią na pytanie? Byłoby to bardzo pomocne dla osoby zadającej pytanie i każdej innej, która się pojawi.
Andrew Barber

18
To jest oczywiste.
Edward Olamisan,

4
Jak to się nie wyjaśnia? Miałem to samo pytanie, od razu zrozumiałem odpowiedź.
DanteTheSmith

1
Czym różni się ta odpowiedź od @TcK poza konwencją nazewnictwa?
Sushil Jadhav

7

Co powiesz na to:

BEGIN
   Do Something
END
GO 10

... oczywiście możesz włożyć do niej przyrostowy licznik, jeśli musisz liczyć.


3
„GO 10”? SQL Server 2008 tego nie lubi.
Zasób

7

Pętla For nie jest jeszcze oficjalnie obsługiwana przez serwer SQL. Istnieje już odpowiedź na temat osiągania różnych sposobów FOR Loop. Szczegółowo przedstawiam odpowiedź na temat sposobów uzyskania różnych typów pętli w serwerze SQL.

Dla pętli

DECLARE @cnt INT = 0;

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

PRINT 'Done FOR LOOP';

Jeśli wiesz, musisz mimo to wykonać pierwszą iterację pętli, możesz wypróbować DO..WHILE lub REPEAT..UNTIL wersję serwera SQL.

DO..HILE Loop

DECLARE @X INT=1;

WAY:  --> Here the  DO statement

  PRINT @X;

  SET @X += 1;

IF @X<=10 GOTO WAY;

REPEAT..UNTIL Pętla

DECLARE @X INT = 1;

WAY:  -- Here the REPEAT statement

  PRINT @X;

  SET @X += 1;

IFNOT(@X > 10) GOTO WAY;

Odniesienie


Wygląda na to, że tutaj skopiowano-wklejono-zmieniono kolejność: stackoverflow.com/a/46363319/8239061
SecretAgentMan

@SecretAgentMan: Obie odpowiedzi odpowiadają na różne pytania. Dodatkowe dane podane w obu odpowiedziach.
Somnath Muluk

6

Prosta odpowiedź brzmi NO !!.

Nie ma FORSQL, ale możesz użyć WHILElub GOTOosiągnąć sposób, w jaki FORbędzie działać.

PODCZAS :

DECLARE @a INT = 10

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

IŚĆ DO :

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

Ja zawsze wolę WHILEnad GOTOoświadczeniem.


1
Podoba mi się, jak wspomniałeś obie alternatywy zamiast 1, jak większość odpowiedzi
DanteTheSmith

0

Podczas gdy przykład Pętli w języku T-SQL, który wyświetla datę początku i końca bieżącego miesiąca.

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;  

0

Wypróbuj, naucz się:

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

Z datą:

DECLARE @d DATE = '2019-11-01'
WHILE @d < GETDATE()
BEGIN
    PRINT @d
    SET @d = DATEADD(DAY,1,@d)
END
PRINT 'n'
PRINT @d
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.