Есть ли какой-либо метод для реализации do while
цикла в SQL Server 2008?
Есть ли какой-либо метод для реализации do while
цикла в SQL Server 2008?
Ответы:
Я не уверен насчет 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
Но старайтесь избегать петель на уровне базы данных. Ссылка .
Если вас не очень обидело 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
.
Кажется, я припоминаю, что читал эту статью не один раз, и ответ близок только к тому, что мне нужно.
Обычно, когда я думаю, что мне понадобится 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 не предлагает более чистого способа одиночного определения операции цикла, чем этот бесконечный цикл.
Вы также можете использовать переменную выхода, если хотите, чтобы ваш код был более читабельным:
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
Это, вероятно, будет более уместно, если у вас более сложный цикл и вы пытаетесь отслеживать логику. Как указано, циклы дороги, поэтому попробуйте использовать другие методы, если можете.
Только цикл пока официально поддерживается SQL-сервером. Уже есть ответ на цикл DO while. Я подробно рассказываю о способах достижения различных типов циклов на SQL-сервере.
Если вы знаете, что вам все равно нужно завершить первую итерацию цикла, вы можете попробовать версию SQL-сервера DO..WHILE или REPEAT..UNTIL .
DECLARE @X INT=1;
WAY: --> Here the DO statement
PRINT @X;
SET @X += 1;
IF @X<=10 GOTO WAY;
DECLARE @X INT = 1;
WAY: -- Here the REPEAT statement
PRINT @X;
SET @X += 1;
IFNOT(@X > 10) GOTO WAY;
DECLARE @cnt INT = 0;
WHILE @cnt < 10
BEGIN
PRINT 'Inside FOR LOOP';
SET @cnt = @cnt + 1;
END;
PRINT 'Done FOR LOOP';