Цикл выполнения в SQL Server 2008 - PullRequest
114 голосов
/ 20 декабря 2010

Есть ли способ реализовать цикл do while в SQL Server 2008?

Ответы [ 5 ]

180 голосов
/ 20 декабря 2010

Я не уверен насчет 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/

  1. Пример цикла 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
    
  2. Пример цикла 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
    
  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
    

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

58 голосов
/ 28 июня 2011

Если вы не очень обижены ключевым словом 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разрешенное решение и оригинальный 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.

18 голосов
/ 12 марта 2014

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

Обычно, когда я думаю, что мне понадобится 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 голосов
/ 07 мая 2015

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

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

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

1 голос
/ 22 сентября 2017

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

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

DO..WHILE Loop

DECLARE @X INT=1;

WAY:  --> Here the  DO statement

  PRINT @X;

  SET @X += 1;

IF @X<=10 GOTO WAY;

REPEAT..TUN Loop

DECLARE @X INT = 1;

WAY:  -- Here the REPEAT statement

  PRINT @X;

  SET @X += 1;

IFNOT(@X > 10) GOTO WAY;

ДЛЯ Loop

DECLARE @cnt INT = 0;

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

PRINT 'Done FOR LOOP';

Ссылка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...