SQL Server中for循环的语法
Posted
技术标签:
【中文标题】SQL Server中for循环的语法【英文标题】:Syntax of for-loop in SQL Server 【发布时间】:2011-08-29 11:13:50 【问题描述】:TSQL 中for
循环的语法是什么?
【问题讨论】:
SQL 与您习惯的语言相比是一种非常不同的语言。它关注的是what,而不是how。你告诉 SQL Server 你想要什么结果,然后让它弄清楚如何产生答案。或者,重新表述一下我刚才所说的 - SQL 中没有 for 循环。WHILE @I < 10; SET @I = @I + 1; BEGIN; ...; END
?但是,这应该不用于大多数查询处理(但有时需要用于命令式操作)。使用搜索“tsql for loop”可以在 google 上找到许多这样的说明/提示。
避免循环以支持 JOIN 和集合操作。
如果您不是 SQL 专家,则不应考虑使用循环。只有少数情况需要使用循环,而在其余大部分时间,使用循环相当于推动汽车而不是驾驶汽车。学会从数据集的角度思考,而不是遍历记录。 LOoping 是一个专家级功能,不是因为语法难,而是因为你需要确切知道你可以用它造成多大的伤害,然后才能被允许使用它。
有时它可以用来在测试数据库中快速生成测试数据,无论如何你很快就会删除这些数据。在这种情况下,使用它消除了通过类似 C# 编写的单独程序的需要,并且工程并不是特别重要的问题。再说一次,我只是在测试数据方面这么说。
【参考方案1】:
旧线程但仍在出现,我想我会为需要的人提供“FOREACH”解决方案。
DECLARE @myValue nvarchar(45);
DECLARE myCursor CURSOR FOR
SELECT [x]
FROM (Values ('Value1'),('Value2'),('Value3'),('Value4'))
as MyTable(x);
OPEN myCursor;
FETCH NEXT FROM myCursor INTO @myValue;
While (@@FETCH_STATUS = 0)
BEGIN
PRINT @myValue
FETCH NEXT FROM myCursor INTO @myValue;
END
CLOSE myCursor;
DEALLOCATE myCursor;
我应该声明一下,递归在 SQL 世界中是不受欢迎的。并且有充分的理由 - 它可能对性能非常不利。不过,对于维护/离线/批量/临时/测试/等操作,我经常使用这种方法。
【讨论】:
【参考方案2】:额外信息
只是补充一下,因为没有人发布了一个答案,其中包括如何在循环内实际迭代数据集。您可以使用关键字OFFSET FETCH。
用法
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
【讨论】:
使用光标的好选择。 这不是一遍又一遍地执行选择吗?特别是如果它是一个连接并且不能每次都转到特定的行号?【参考方案3】:尝试一下,学习一下:
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
日期:
DECLARE @d DATE = '2019-11-01'
WHILE @d < GETDATE()
BEGIN
PRINT @d
SET @d = DATEADD(DAY,1,@d)
END
PRINT 'n'
PRINT @d
【讨论】:
【参考方案4】:T-SQL 中的 While 循环示例,列出当前月份的开始到结束日期。
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;
【讨论】:
【参考方案5】:SQL Server 尚未正式支持 For 循环。已经有answer 关于实现FOR Loop 的不同方式。我正在详细解答在 SQL Server 中实现不同类型循环的方法。
FOR 循环
DECLARE @cnt INT = 0;
WHILE @cnt < 10
BEGIN
PRINT 'Inside FOR LOOP';
SET @cnt = @cnt + 1;
END;
PRINT 'Done FOR LOOP';
如果您知道,无论如何您都需要完成循环的第一次迭代,那么您可以尝试 DO..WHILE 或 REPEAT..UNTIL 版本的 SQL Server。
DO..WHILE 循环
DECLARE @X INT=1;
WAY: --> Here the DO statement
PRINT @X;
SET @X += 1;
IF @X<=10 GOTO WAY;
REPEAT..UNTIL 循环
DECLARE @X INT = 1;
WAY: -- Here the REPEAT statement
PRINT @X;
SET @X += 1;
IFNOT(@X > 10) GOTO WAY;
Reference
【讨论】:
这似乎已在此处复制-粘贴-重新排序:***.com/a/46363319/8239061 @SecretAgentMan:两个答案都在回答不同的问题。两个答案中都给出了额外的数据。 问题并没有太大的不同。我认为它们是重复的。【参考方案6】:T-SQL 没有FOR
循环,它有一个WHILE
循环WHILE (Transact-SQL)
WHILE Boolean_expression
BEGIN
END
【讨论】:
JOIN(和集合操作)应该优先于 SQL 中的循环结构。 强调没有限制(特别是对于那些刚接触 SQL 的人),正如 Damien 所说:“与你习惯的语言相比,SQL 是一种非常不同的语言。它专注于关于什么,而不是如何。你告诉 SQL Server 你想要什么结果,然后让它弄清楚如何产生答案。" 有趣的是,这里的 MS 文档是错误的,真的。 WHILE 不采用布尔表达式 - 它采用谓词 - 除了能够评估为 TRUE 或 FALSE 之外,还可能是 UNKNOWN。【参考方案7】:这个怎么样:
BEGIN
Do Something
END
GO 10
...当然,如果需要计数,您可以在其中放置一个增量计数器。
【讨论】:
'GO 10'? SQL Server 2008 不喜欢它。【参考方案8】:没有for循环,只有while循环:
DECLARE @i int = 0
WHILE @i < 20
BEGIN
SET @i = @i + 1
/* do some work */
END
【讨论】:
请注意,如果您打算在循环中使用索引,您可能希望增加最后一项而不是第一项,具体取决于您的用例。 另请注意,普通 SQL 不支持局部变量的默认值。因此,在 for 循环之前您需要单独的SET @i = 0
。
@Nux:0 是在声明期间明确设置的
是的,但这不适用于较旧的 SQL Server(至少在 2005 年不适用)。
另外,应该注意的是,通常工作是在整数递增之前完成的。 SQL 中的许多 for 循环实际上在其工作中使用该整数(从行到行或结果迭代以生成临时表)并且如果增量发生在循环开始而不是结束时可能会被丢弃。跨度>
【参考方案9】:
简单的答案是NO !!
。
SQL中没有
FOR
,但是可以使用WHILE
或者GOTO
来实现FOR
的工作方式。
同时:
DECLARE @a INT = 10
WHILE @a <= 20
BEGIN
PRINT @a
SET @a = @a + 1
END
转到:
DECLARE @a INT = 10
a:
PRINT @a
SET @a = @a + 1
IF @a < = 20
BEGIN
GOTO a
END
我总是更喜欢 WHILE
而不是 GOTO
声明。
【讨论】:
我喜欢你提到的两种选择,而不是像大多数答案一样只有 1 个【参考方案10】:DECLARE @intFlag INT
SET @intFlag = 1
WHILE (@intFlag <=5)
BEGIN
PRINT @intFlag
SET @intFlag = @intFlag + 1
END
GO
【讨论】:
欢迎来到 Stack Overflow!您是否会考虑添加一些叙述来解释为什么此代码有效,以及是什么使它成为问题的答案?这对提出问题的人以及其他任何出现的人都非常有帮助。 这是不言自明的。 这怎么不是不言自明的?我有同样的问题,我马上明白了答案。 除了命名约定之外,这个答案与@TcKs 有何不同?以上是关于SQL Server中for循环的语法的主要内容,如果未能解决你的问题,请参考以下文章