T-SQL 循环查询结果
Posted
技术标签:
【中文标题】T-SQL 循环查询结果【英文标题】:T-SQL loop over query results 【发布时间】:2012-08-07 19:29:50 【问题描述】:我运行了一个查询 select @id=table.id from table
,我需要遍历结果,以便为每一行执行一个存储过程 exec stored_proc @varName=@id,@otherVarName='test'
如何在 T-SQL 脚本中执行此操作?
【问题讨论】:
好吧,我什么都没试过。我不知道该怎么做。我想我可以尝试编写一个C
样式循环,但我怀疑这会奏效。也许是一个php
风格的循环,但我再次怀疑这也行得通。我需要在 T-SQL 中完成这一切,因为我可以在 SMS 中运行 SQL,而无需外部语言进行循环......首先是这个问题。
@Shedal 这些 cmets/answers(尽管比“google it”答案少)具有讽刺意味的是,随着时间的推移,它们往往会成为谷歌搜索结果中的佼佼者。因此,反过来,当有人寻找某个问题的解决方案时,他首先会遇到的是对遇到问题但自己没有费心寻找答案的其他人的抨击(通常是有道理的)。从长远来看,这会让那些真正试图寻找答案的人感到厌烦。
@MarcinHabuszewski 好吧,老实说,如果一个常见问题没有正确答案,它就不会出现在 Google 搜索结果的第一页上。正常。
【参考方案1】:
在这种情况下,您可以使用 CURSOR:
DECLARE @id INT
DECLARE @name NVARCHAR(100)
DECLARE @getid CURSOR
SET @getid = CURSOR FOR
SELECT table.id,
table.name
FROM table
OPEN @getid
FETCH NEXT
FROM @getid INTO @id, @name
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC stored_proc @varName=@id, @otherVarName='test', @varForName=@name
FETCH NEXT
FROM @getid INTO @id, @name
END
CLOSE @getid
DEALLOCATE @getid
修改为显示表格中的多个参数。
【讨论】:
如果你想从表中获取超过 id 怎么办? @HenleyChiu 我已经修改了答案以包含一个我相信会起作用的新参数@name
,但是我现在已经有一段时间没有使用光标了!。
@XN16 使用超过 id 不起作用,必须找到解决方法:-(【参考方案2】:
你可以这样做:
create procedure test
as
BEGIN
create table #ids
(
rn int,
id int
)
insert into #ids (rn, id)
select distinct row_number() over(order by id) as rn, id
from table
declare @id int
declare @totalrows int = (select count(*) from #ids)
declare @currentrow int = 0
while @currentrow < @totalrows
begin
set @id = (select id from #ids where rn = @currentrow)
exec stored_proc @varName=@id, @otherVarName='test'
set @currentrow = @currentrow +1
end
END
【讨论】:
我更喜欢这种方法,因为光标比while循环慢 与 set 操作(即制作一个大的选择/更新语句)相比,游标更慢。与创建临时表和做一些 writes 相比,我不太确定。请参阅techrepublic.com/blog/the-enterprise-cloud/… 我做了自己的测试,我同意。当您遇到锁定问题时,临时表可能会更快,并且您可以更快地获取子集然后对其进行处理。这取决于我猜... 在 SQL Server 上,这在循环的第一次迭代中给了我一个错误,因为 row_number() 从 1 开始,但 @currentrow 被初始化为 0【参考方案3】:我更喜欢的解决方案是 Microsoft KB 111401 http://support.microsoft.com/kb/111401。
链接指的是3个例子:
本文介绍了可用于在存储过程、触发器或 Transact-SQL 批处理中模拟类似游标的 FETCH-NEXT 逻辑的各种方法。
/*********** example 1 ***********/
declare @au_id char( 11 )
set rowcount 0
select * into #mytemp from authors
set rowcount 1
select @au_id = au_id from #mytemp
while @@rowcount <> 0
begin
set rowcount 0
select * from #mytemp where au_id = @au_id
delete #mytemp where au_id = @au_id
set rowcount 1
select @au_id = au_id from #mytemp
end
set rowcount 0
/********** example 2 **********/
declare @au_id char( 11 )
select @au_id = min( au_id ) from authors
while @au_id is not null
begin
select * from authors where au_id = @au_id
select @au_id = min( au_id ) from authors where au_id > @au_id
end
/********** example 3 **********/
set rowcount 0
select NULL mykey, * into #mytemp from authors
set rowcount 1
update #mytemp set mykey = 1
while @@rowcount > 0
begin
set rowcount 0
select * from #mytemp where mykey = 1
delete #mytemp where mykey = 1
set rowcount 1
update #mytemp set mykey = 1
end
set rowcount 0
【讨论】:
【参考方案4】:DECLARE @id INT
DECLARE @name NVARCHAR(100)
DECLARE @getid CURSOR
SET @getid = CURSOR FOR
SELECT table.id,
table.name
FROM table
WHILE 1=1
BEGIN
FETCH NEXT
FROM @getid INTO @id, @name
IF @@FETCH_STATUS < 0 BREAK
EXEC stored_proc @varName=@id, @otherVarName='test', @varForName=@name
END
CLOSE @getid
DEALLOCATE @getid
【讨论】:
只需在“WHILE 1=1”之前添加“OPEN @getid”【参考方案5】:DECLARE @id INT
DECLARE @filename NVARCHAR(100)
DECLARE @getid CURSOR
SET @getid = CURSOR FOR
SELECT top 3 id,
filename
FROM table
OPEN @getid
WHILE 1=1
BEGIN
FETCH NEXT
FROM @getid INTO @id, @filename
IF @@FETCH_STATUS < 0 BREAK
print @id
END
CLOSE @getid
DEALLOCATE @getid
【讨论】:
【参考方案6】:试试这个:
declare @i tinyint = 0,
@count tinyint,
@id int,
@name varchar(max)
select @count = count(*) from table
while (@i < @count)
begin
select @id = id, @name = name from table
order by nr asc offset @i rows fetch next 1 rows only
exec stored_proc @varName = @id, @otherVarName = 'test', @varForName = @name
set @i = @i + 1
end
【讨论】:
以上是关于T-SQL 循环查询结果的主要内容,如果未能解决你的问题,请参考以下文章