在 SQL 服务器上迭代游标时如何知道最后一行?
How to know last row when iterating cursor on SQL Server?
在 SQL 服务器上迭代游标时如何知道最后一行?
我试过计数器和 @@CURSOR_ROWS
和 @@FETCH_STATUS
,但效果不佳或者我没有正确使用它们。
编辑:
嗯,是的,在每个循环的末尾用逗号组成字符串... ,
。当然,在 return 之前我可以切断最后一个字符 ,
但我想知道这是唯一的方法吗?
但是,有很多情况,知道如何识别最后一行可能会很好。
正如评论中所建议的,通过对 first 行而不是最后一行做一些特殊的事情,可以更容易地在元素之间放置逗号。1 ,2
而不是
WHILE @@FETCH_STATUS=0
BEGIN
SET @value = @value + @newelement + ','
...
END
并尝试弄清楚如何特别处理最后一行,这样做要容易得多:
SET @first = 1
WHILE @@FETCH_STATUS=0
BEGIN
IF @first = 1
SET @first = 0
ELSE
SET @value = @value + ','
SET @value = @value + @newelement
...
END
如果您确实需要为最后一行做一些事情,另一种转换是使用中间变量和非标准游标循环:
declare boris cursor for select top 10 name from sys.objects order by name
declare @name sysname
declare @nametemp sysname
open boris
fetch next from boris into @nametemp
while @@FETCH_STATUS=0
BEGIN
set @name = @nametemp --Use SELECT if multiple variables to be assigned
fetch next from boris into @nametemp
if @@FETCH_STATUS!=0
begin
print 'and finally'
end
print @name
END
close boris
deallocate boris
打印(对我来说,在几乎空的数据库中):
EventNotificationErrorsQueue
filestream_tombstone_2073058421
filetable_updates_2105058535
IsIt
QueryNotificationErrorsQueue
queue_messages_1977058079
queue_messages_2009058193
queue_messages_2041058307
ServiceBrokerQueue
and finally
sysallocunits
但我强烈建议改用第一种类型的转换。
1这也不仅仅是 T-SQL 的事情。在大多数编程语言中,如果您可以将问题从 "treat the last iteration differently" 转换为 "treat the first iteration differently"
通常会容易得多
2当然,在 SQL 中插入关于游标是最后手段的常见警告,除非或直到它们被证明可以使用基于集合的方法不足。
也可以使用FETCH后的条件:
DECLARE @sqlStatement nvarchar(max) = '(';
DECLARE @column_name nvarchar(255);
DECLARE colums CURSOR FOR
SELECT TOP 10 name FROM sys.all_columns
OPEN colums
FETCH NEXT FROM colums INTO @column_name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sqlStatement = @sqlStatement
+ QUOTENAME(@column_name)
FETCH NEXT FROM colums INTO @column_name
SET @sqlStatement = @sqlStatement + CASE WHEN @@FETCH_STATUS != -1 THEN ',' ELSE ')' END
+ char(13)
END
CLOSE colums
DEALLOCATE colums
print @sqlStatement
在 SQL 服务器上迭代游标时如何知道最后一行?
我试过计数器和 @@CURSOR_ROWS
和 @@FETCH_STATUS
,但效果不佳或者我没有正确使用它们。
编辑:
嗯,是的,在每个循环的末尾用逗号组成字符串... ,
。当然,在 return 之前我可以切断最后一个字符 ,
但我想知道这是唯一的方法吗?
但是,有很多情况,知道如何识别最后一行可能会很好。
正如评论中所建议的,通过对 first 行而不是最后一行做一些特殊的事情,可以更容易地在元素之间放置逗号。1 ,2
而不是
WHILE @@FETCH_STATUS=0
BEGIN
SET @value = @value + @newelement + ','
...
END
并尝试弄清楚如何特别处理最后一行,这样做要容易得多:
SET @first = 1
WHILE @@FETCH_STATUS=0
BEGIN
IF @first = 1
SET @first = 0
ELSE
SET @value = @value + ','
SET @value = @value + @newelement
...
END
如果您确实需要为最后一行做一些事情,另一种转换是使用中间变量和非标准游标循环:
declare boris cursor for select top 10 name from sys.objects order by name
declare @name sysname
declare @nametemp sysname
open boris
fetch next from boris into @nametemp
while @@FETCH_STATUS=0
BEGIN
set @name = @nametemp --Use SELECT if multiple variables to be assigned
fetch next from boris into @nametemp
if @@FETCH_STATUS!=0
begin
print 'and finally'
end
print @name
END
close boris
deallocate boris
打印(对我来说,在几乎空的数据库中):
EventNotificationErrorsQueue
filestream_tombstone_2073058421
filetable_updates_2105058535
IsIt
QueryNotificationErrorsQueue
queue_messages_1977058079
queue_messages_2009058193
queue_messages_2041058307
ServiceBrokerQueue
and finally
sysallocunits
但我强烈建议改用第一种类型的转换。
1这也不仅仅是 T-SQL 的事情。在大多数编程语言中,如果您可以将问题从 "treat the last iteration differently" 转换为 "treat the first iteration differently"
通常会容易得多2当然,在 SQL 中插入关于游标是最后手段的常见警告,除非或直到它们被证明可以使用基于集合的方法不足。
也可以使用FETCH后的条件:
DECLARE @sqlStatement nvarchar(max) = '(';
DECLARE @column_name nvarchar(255);
DECLARE colums CURSOR FOR
SELECT TOP 10 name FROM sys.all_columns
OPEN colums
FETCH NEXT FROM colums INTO @column_name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sqlStatement = @sqlStatement
+ QUOTENAME(@column_name)
FETCH NEXT FROM colums INTO @column_name
SET @sqlStatement = @sqlStatement + CASE WHEN @@FETCH_STATUS != -1 THEN ',' ELSE ')' END
+ char(13)
END
CLOSE colums
DEALLOCATE colums
print @sqlStatement