2012-08-07 9 views
47

uruchomić kwerendę select @id=table.id from table i muszę pętli nad wynikami więc mogę exec procedurę sklep dla każdego wiersza exec stored_proc @[email protected],@otherVarName='test'T-SQL w pętli nad wyników zapytania

Jak mogę to zrobić w skrypcie T-SQL?

+0

dobrze, nie próbowałem niczego. Nie wiem, jak to zrobić. Przypuszczam, że mógłbym spróbować napisać pętlę w stylu "C", ale wątpię, że to zadziała. Może pętla w stylu PHP, ale znowu wątpię, że to zadziała. Muszę zrobić to wszystko w języku T-SQL, ponieważ mogę uruchamiać SQL w SMS-ach bez zewnętrznego języka, który wykonuje pętlę ... Najpierw skoncentruj się na tym pytaniu. – Justin808

+1

@Shedal Ironia tych komentarzy/odpowiedzi (choć jest mniejsza niż odpowiedzi "google it") polega na tym, że z biegiem czasu stają się one najlepszymi wynikami Google. Tak więc z kolei, gdy ktoś szuka rozwiązania jakiegoś problemu, pierwszą rzeczą, którą spotka, jest bashowanie (zwykle uzasadnione) kogoś, kto miał problem, ale który nie zadał sobie trudu, by samemu znaleźć odpowiedź. Na dłuższą metę staje się irytujące dla osób, które rzeczywiście próbują szukać odpowiedzi. – jahu

+0

@MarcinHabuszewski dobrze, szczerze mówiąc, w przypadku braku właściwej odpowiedzi na częste pytanie, nie pojawi się na pierwszej stronie wyników wyszukiwania Google. Zwykle. –

Odpowiedz

124

Można użyć kursora w tym przypadku:

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 

Modified pokazać wiele parametrów z tabeli.

+1

co, jeśli chcesz uzyskać więcej niż id ze stołu? –

+2

@HenleyChiu Mam zmodyfikowany odpowiedź na to nowy parametr '@ name' że sądzić będzie działać, ale to było dawno Użyłem kursor teraz !. – XN16

+0

@ XN16 użyciu więcej niż id nie działa, obejść musi znaleźć :-( –

12

Można zrobić coś takiego:

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

Lubię ten sposób lepsze od kursora są wolniejsze niż pętli while –

+2

kursory są wolniejsze w porównaniu do ustawienia operacji (czyli umacnianie jeden duży wybór/instrukcja aktualizacji) W porównaniu do tworzenia tabeli tymczasowej i wykonywania niektórych _writes_ nie jestem tego taki pewien. Patrz: http://www.techrepublic.com/blog/the-enterprise-cloud/comparing-cursor-vs-while-loop- wydajność-in-sql-server-2008/ zrobiłem własne testy i zgadzam się. Ewentualnie tabeli temp jest szybsza, gdy masz problemy blokowania można uzyskać podzbiór szybciej, a następnie przetwarza je. to zależy Chyba .. . –

6

My wolą rozwiązaniem jest Microsoft KB 111401 http://support.microsoft.com/kb/111401.

Związek przykładów odnosi się do 3:

Artykuł ten opisuje różne metody, które można użyć, aby symulować kursora jak pobieranych ręcznie NEXT logiki procedury przechowywanej, wyzwalacz lub Transact-SQL partii.

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

spróbować tego:

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 
Powiązane problemy