2012-08-07 15 views
47

que ejecuta una consulta select @id=table.id from table y necesito un bucle sobre los resultados, así que puede exec un procedimiento de almacenamiento para cada fila exec stored_proc @[email protected],@otherVarName='test'T-SQL bucle sobre resultados de la consulta

¿Cómo puedo hacer esto en un script T-SQL?

+0

bien, Yo no probar nada. No sé cómo hacerlo. Supongo que podría intentar escribir un ciclo de estilo 'C', pero dudo que eso funcione. Tal vez un loop de estilo 'PHP', pero nuevamente dudo que eso funcione también. Necesito hacerlo todo en T-SQL porque puedo ejecutar el SQL en SMS sin un lenguaje externo haciendo el bucle ... En primer lugar, la pregunta. – Justin808

+1

@Shedal La ironía de esos comentarios/respuestas (aunque menos que las respuestas de "google it") es que, con el tiempo, tienden a convertirse en los principales resultados de Google. Por lo tanto, cuando alguien busca una solución al problema, lo primero que encuentra es un ataque (generalmente justificado) de otra persona que tuvo el problema, pero que no se molestó en buscar la respuesta por sí mismo. A la larga, se vuelve molesto para las personas que realmente intentan buscar la respuesta. – jahu

+0

@MarcinHabuszewski bien, para ser honesto, en caso de que no haya una respuesta adecuada para una pregunta común, no aparecerá en la primera página de los resultados de búsqueda de Google. Normalmente. –

Respuesta

124

Se puede usar un cursor en este caso:

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 

Modificado para mostrar múltiples parámetros de la tabla.

+1

¿Qué sucede si quiere obtener más que una identificación de la mesa? –

+2

@HenleyChiu He modificado la respuesta para incluir un nuevo parámetro '@ nombre' que creo que funcionará, pero ha pasado un tiempo desde que he usado un cursor ahora !. – XN16

+0

@ XN16 usando más de id no funcionó, hay que encontrar la solución :-( –

12

Se podría hacer algo como esto:

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

Me gusta más este método porque el cursor es más lento que while loop –

+2

Los cursores son más lentos en comparación con las operaciones establecidas (es decir, crear una gran selección/declaración de actualización). En comparación con la creación de una tabla temporal y la realización de algunas _escrituras_ no estoy tan seguro. Consulte http://www.techrepublic.com/blog/the-enterprise-cloud/comparing-cursor-vs-while-loop- performance-in-sql-server-2008/ Hice mis propias pruebas y estoy de acuerdo. Posiblemente una tabla temporal es más rápida cuando tiene problemas de bloqueo y puede obtener su subconjunto más rápido y luego procesarlo. Depende, supongo ... . –

6

Mi prefieren solución es Microsoft KB 111401 http://support.microsoft.com/kb/111401.

El enlace se refiere a 3 ejemplos:

Este artículo describe varios métodos que se pueden utilizar para simular una lógica FETCH-NEXT cursor-como en un procedimiento almacenado, disparador, o lote de 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

probar esto:

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 
Cuestiones relacionadas