Есть ли какой-либо метод для реализации цикла do while
в SQL Server 2008?
Выполнять цикл 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';