2012-08-07 89 views
47

我運行一個查詢select @id=table.id from table,我需要循環的結果,所以我可以Exec中的存儲過程的每一行exec stored_proc @[email protected],@otherVarName='test'T-SQL遍歷查詢結果

我怎樣才能在T-SQL腳本做到這一點?

+0

好,我沒有嘗試任何事情。我不知道該怎麼做。我想我可以嘗試編寫一個'C'風格的循環,但我懷疑這會起作用。也許是一個'PHP'風格的循環,但我懷疑這也會起作用。我需要在T-SQL中完成所有工作,因爲我可以在SMS中運行SQL,而無需使用外部語言進行循環......首先提升問題。 – Justin808 2012-08-07 19:35:26

+1

@Shedal這些評論/回答的諷刺(雖然不及「谷歌它」的答案)是,隨着時間的推移,他們往往成爲谷歌的頂級成績。因此,當有人尋找解決某個問題的辦法時,他會遇到的第一件事是對其他有問題的人進行抨擊(通常是合理的),但是誰也懶得自己去尋找答案。從長遠來看,實際上試圖尋找答案的人變得煩人。 – jahu 2014-05-28 10:14:25

+0

@MarcinHabuszewski好吧,說實話,如果對常見問題沒有適當的答案,它就不會顯示在Google搜索結果的第一頁上。一般。 – 2014-05-28 13:38:09

回答

124

你可以在這種情況下使用遊標:

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 @[email protected], @otherVarName='test', @[email protected] 
    FETCH NEXT 
    FROM @getid INTO @id, @name 
END 

CLOSE @getid 
DEALLOCATE @getid 

修改以顯示從表中多個參數。

+1

如果你想從表中獲得更多的id,該怎麼辦? – 2013-10-03 20:09:40

+2

@HenleyChiu我已經修改了答案,以包含一個新的參數'@ name',我相信會起作用,但它已經有一段時間了,因爲我現在已經使用了一個光標! – XN16 2013-10-04 07:35:28

+0

@ XN16使用多於id沒有工作,必須找到解決辦法:-( – 2014-12-08 21:33:46

12

你可以做這樣的事情:

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 @[email protected], @otherVarName='test' 

     set @currentrow = @currentrow +1 
    end 

END 
+0

我喜歡這個方法更好,因爲光標比while循環更慢 – 2015-11-09 15:00:58

+2

與set操作相比,遊標速度更慢(即製作一個大的select /更新語句)。與創建臨時表和做一些_writes_相比,我不太確定。請參閱http://www.techrepublic.com/blog/the-enterprise-cloud/comparing-cursor-vs-while-loop-性能在sql-server-2008/ 我做了我自己的測試,我同意 當你有鎖定問題,並且你可以更快地處理你的子集,然後處理它,這可能是一個臨時表。 。 – 2016-05-10 13:31:35

6

我喜歡的解決方案是微軟KB 111401 http://support.microsoft.com/kb/111401

的鏈路是指3點的例子:

本文介紹的各種方法,可以使用在存儲過程中,觸發以模擬光標狀FETCH-NEXT邏輯,或Transact-SQL批處理。

/********** 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<BR/> 
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 
0

試試這個:

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 
1
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 @[email protected], @otherVarName='test', @[email protected] 

END 

CLOSE @getid 
DEALLOCATE @getid