T-SQL遍历查询结果


76

我运行查询select @id=table.id from table,我需要遍历结果,以便可以对每一行执行存储过程exec stored_proc @varName=@id,@otherVarName='test'

如何在T-SQL脚本中执行此操作?


好吧,我什么也没尝试。我不知道该怎么做。我想我可以尝试编写一个C样式循环,但是我怀疑这样做是否可行。也许是一个PHP样式循环,但是我再次怀疑这是否也会奏效。我需要在T-SQL中完成所有操作,因为我可以在SMS中运行SQL,而无需使用外部语言进行循环...首先要解决这个问题。
Justin808 2012年

2
@Shedal具有讽刺意味的是,这些评论/答案(尽管比“ google it”答案要少)是,随着时间的推移,它们往往会成为Google的最佳搜索结果。因此,反过来,当某人寻找某个问题的解决方案时,他会遇到的第一件事就是扑打(通常是有道理的)其他遇到问题但没有费心自己寻找答案的人。从长远来看,这会让真正尝试寻找答案的人感到烦恼。
2014年

@MarcinHabuszewski很好,老实说,如果对于一个常见问题没有正确的答案,它将不会显示在Google搜索结果的首页上。一般。
Dmytro Shevchenko

Answers:


172

在这种情况下,您可以使用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

修改以显示表中的多个参数。


1
如果您想从表中获取更多信息,该怎么办?
亨利·邱

2
@HenleyChiu我修改了答案,以包含一个@name我认为可以使用的新参数,但是自从我现在使用光标以来已经有一段时间了!
2013年

@ XN16使用ID大于ID无效,必须找到解决方法:-(
Zaveed Abbasi 2014年

22

您可以执行以下操作:

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

我喜欢这种方法更好,因为游标比而较慢的循环
PL Audet

3
与设置操作(例如,编写一条大的select / update语句)相比,游标的速度较慢。与创建临时表和执行一些写操作相比,我不确定。看到techrepublic.com/blog/the-enterprise-cloud / ...我做了自己的测试,我同意。遇到锁定问题时,临时表可能会更快,并且可以更快地获取子集然后进行处理。我猜这取决于...
phil_w

在SQL Server上,这在循环的第一次迭代中给了我一个错误,因为row_number()从1开始,但@currentrow被初始化为0
samgak

8

我更喜欢的解决方案是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

3
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

之前“而1 = 1”加“OPEN @getid”
伊恩

0
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

-1

试试这个:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.