Выполнять цикл while в SQL Server 2008

Есть ли какой-либо метод для реализации цикла do while в SQL Server 2008?

Ответ 1

Я не уверен в DO-WHILE в MS SQL Server 2008, но вы можете изменить логику цикла WHILE, чтобы ИСПОЛЬЗОВАТЬ, как цикл DO-WHILE.

Примеры взяты здесь: http://blog.sqlauthority.com/2007/10/24/sql-server-simple-example-of-while-loop-with-continue-and-break-keywords/

  • Пример цикла WHILE

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

    ResultSet:

    1
    2
    3
    4
    5
    
  • Пример цикла WHILE с ключевым словом BREAK

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

    ResultSet:

    1
    2
    3
    
  • Пример цикла WHILE с ключевыми словами CONTINUE и BREAK

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
        CONTINUE;
        IF @intFlag = 4 -- This will never executed
            BREAK;
    END
    GO
    

    ResultSet:

    1
    2
    3
    4
    5
    

Но попробуйте избежать циклов на уровне базы данных. Ссылка.

Ответ 2

Если вы не очень обиделись на ключевое слово GOTO, его можно использовать для имитации DO/WHILE в T-SQL. Рассмотрим следующий довольно бессмысленный пример, написанный в псевдокоде:

SET I=1
DO
 PRINT I
 SET I=I+1
WHILE I<=10

Вот эквивалентный код T-SQL с использованием goto:

DECLARE @I INT=1;
START:                -- DO
  PRINT @I;
  SET @I+=1;
IF @I<=10 GOTO START; -- WHILE @I<=10

Обратите внимание на одно к одному сопоставление между решением GOTO enabled и исходным псевдокодом DO/WHILE. Аналогичная реализация с использованием цикла WHILE будет выглядеть так:

DECLARE @I INT=1;
WHILE (1=1)              -- DO
 BEGIN
  PRINT @I;
  SET @I+=1;
  IF NOT (@I<=10) BREAK; -- WHILE @I<=10
 END

Теперь вы можете, конечно, переписать этот конкретный пример как простой цикл WHILE, так как это не такой хороший кандидат для конструкции DO/WHILE. Акцент был сделан на примере краткости, а не на применимости, поскольку допустимые случаи, требующие DO/WHILE, встречаются редко.


REPEAT/UNTIL, кто-нибудь (не работает в T-SQL)?

SET I=1
REPEAT
  PRINT I
  SET I=I+1
UNTIL I>10

... и решение на основе GOTO в T-SQL:

DECLARE @I INT=1;
START:                    -- REPEAT
  PRINT @I;
  SET @I+=1;
IF NOT(@I>10) GOTO START; -- UNTIL @I>10

Благодаря творческому использованию GOTO и логической инверсии с помощью ключевого слова NOT существует очень тесная взаимосвязь между исходным псевдокодом и решением на основе GOTO. Аналогичное решение с использованием цикла WHILE выглядит следующим образом:

DECLARE @I INT=1;
WHILE (1=1)       -- REPEAT
 BEGIN
  PRINT @I;
  SET @I+=1;
  IF @I>10 BREAK; -- UNTIL @I>10
 END

Можно сделать аргумент, что для случая REPEAT/UNTIL решение на основе WHILE проще, поскольку условие if не инвертируется. С другой стороны, это также более подробно.

Если бы не все пренебрежительное отношение к использованию GOTO, это может быть даже идиоматическим решением для тех немногих раз, когда эти конкретные (злые) петлевые конструкции необходимы в коде T-SQL ради ясность.

Используйте их по своему усмотрению, пытаясь не терпеть гнев своих коллег-разработчиков, когда они поймают вас с помощью сильно клеветой GOTO.

Ответ 3

Кажется, я вспоминаю эту статью несколько раз, и ответ близок к тому, что мне нужно.

Обычно, когда я думаю, что мне понадобится DO WHILE в T-SQL, потому что я повторяю курсор, и я ищу в значительной степени оптимальную ясность (по сравнению с оптимальной скоростью). В T-SQL, который, похоже, соответствует WHILE TRUE/IF BREAK.

Если этот сценарий привел вас сюда, этот фрагмент может сэкономить вам время. В противном случае, добро пожаловать, я. Теперь я могу быть уверен, что я здесь уже не один раз.:)

DECLARE Id INT, @Title VARCHAR(50)
DECLARE Iterator CURSOR FORWARD_ONLY FOR
SELECT Id, Title FROM dbo.SourceTable
OPEN Iterator
WHILE 1=1 BEGIN
    FETCH NEXT FROM @InputTable INTO @Id, @Title
    IF @@FETCH_STATUS < 0 BREAK
    PRINT 'Do something with ' + @Title
END
CLOSE Iterator
DEALLOCATE Iterator

К сожалению, T-SQL, по-видимому, не предлагает более чистого способа одномерного определения операции цикла, чем этот бесконечный цикл.

Ответ 4

Вы также можете использовать переменную exit, если вы хотите, чтобы ваш код был более читаемым:

DECLARE @Flag int = 0
DECLARE @Done bit = 0

WHILE @Done = 0 BEGIN
    SET @Flag = @Flag + 1
    PRINT @Flag
    IF @Flag >= 5 SET @Done = 1
END

Это, вероятно, будет более актуальным, если у вас будет более сложный цикл и пытайтесь отслеживать логику. Поскольку указанные циклы дороги, поэтому попробуйте использовать другие методы, если сможете.

Ответ 5

Только пока Loop официально поддерживается сервером SQL. Уже есть answer для цикла DO while. Я подробно расскажу о способах достижения различных типов циклов на SQL-сервере.

Если вы знаете, вам нужно выполнить первую итерацию цикла в любом случае, тогда вы можете попробовать версию SQL Server DO..WHILE или REPEAT..UNTIL.

DO..WHILE Loop

DECLARE @X INT=1;

WAY:  --> Here the  DO statement

  PRINT @X;

  SET @X += 1;

IF @X<=10 GOTO WAY;

REPEAT..UNTIL Loop

DECLARE @X INT = 1;

WAY:  -- Here the REPEAT statement

  PRINT @X;

  SET @X += 1;

IFNOT(@X > 10) GOTO WAY;

FOR Loop

DECLARE @cnt INT = 0;

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

PRINT 'Done FOR LOOP';

Ссылка