2010-04-12 8 views
14

Necesito iterar sobre un conjunto de registros de un procedimiento almacenado y ejecutar otro procedimiento almacenado usando cada campo como argumentos. No puedo completar esta iteración en el código. He encontrado muestras en los internets, pero todos parecen lidiar con un contador. No estoy seguro si mi problema involucró un contador. Necesito el equivalente de T-SQL de foreach¿Cómo puedo iterar sobre un conjunto de registros dentro de un procedimiento almacenado?

Actualmente, mi primer procedimiento almacenado almacena su conjunto de registros en una tabla temporal, #mytemp. Supongo que llamaré al procedimiento almacenado secundario de esta manera:

while (something) 
    execute nameofstoredprocedure arg1, arg2, arg3 
end 

Respuesta

16

Debe crear un cursor para recorrer el conjunto de registros.

Tabla de ejemplo:

CREATE TABLE Customers 
(
    CustomerId INT NOT NULL PRIMARY KEY IDENTITY(1,1) 
    ,FirstName Varchar(50) 
    ,LastName VARCHAR(40) 
) 

INSERT INTO Customers VALUES('jane', 'doe') 
INSERT INTO Customers VALUES('bob', 'smith') 

Cursor:

DECLARE @CustomerId INT, @FirstName VARCHAR(30), @LastName VARCHAR(50) 

DECLARE @MessageOutput VARCHAR(100) 

DECLARE Customer_Cursor CURSOR FOR 
    SELECT CustomerId, FirstName, LastName FROM Customers 


OPEN Customer_Cursor 

FETCH NEXT FROM Customer_Cursor INTO 
    @CustomerId, @FirstName, @LastName 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @MessageOutput = @FirstName + ' ' + @LastName 



    RAISERROR(@MessageOutput,0,1) WITH NOWAIT 

    FETCH NEXT FROM Customer_Cursor INTO 
    @CustomerId, @FirstName, @LastName 
END 
CLOSE Customer_Cursor 
DEALLOCATE Customer_Cursor 

Aquí hay un enlace a MSDN sobre cómo crearlos.

http://msdn.microsoft.com/en-us/library/ms180169.aspx

Es por esto que he utilizado error Levante en lugar de impresión para enviar.
http://structuredsight.com/2014/11/24/wait-wait-dont-tell-me-on-second-thought/

+0

Pude portar el enlace eggheadcafe.com a mi código. gracias –

+0

¡El artículo de egghead lo hizo! – PhilNicholas

+0

Esta respuesta se ha marcado para su eliminación porque es una respuesta de solo enlace cuyo enlace ahora está roto. ¿Podría ampliar la respuesta para abordar la pregunta por completo sin que el lector haga clic en el enlace? – josliber

5

probar esto (bucle libre de cursor):

CREATE TABLE #Results (RowID int identity(1,1), Col1 varchar(5), Col2 int, ...) 
DECLARE @Current int 
     ,@End  int 
DECLARE @Col1 varchar(5) 
     ,@Col2 int 
     ,... 

--you need to capture the result set from the primary stored procedure 
INSERT INTO #Results 
    (Col1, COl2,...) 
    EXEC nameofstoredprocedure_1 arg1, arg2, arg3 
SELECT @[email protected]@ROWCOUNT,@Current=0 

--process each row in the result set 
WHILE @Current<@End 
BEGIN 
    SET @[email protected]+1 

    SELECT 
     @Col1=COl1, @Col2=Col2 
     FROM #Results 
     WHERE [email protected] 

    --call the secondary procedure for each row 
    EXEC nameofstoredprocedure_2 @Col1, @Col2,... 

END 

ejemplo de trabajo:

CREATE PROCEDURE nameofstoredprocedure_1 
(@arg1 int, @arg2 int, @arg3 int) 
AS 
SELECT 'AAA',@arg1 UNION SELECT 'BBB',@arg2 UNION SELECT 'CCC',@arg3 
GO 

CREATE PROCEDURE nameofstoredprocedure_2 
(@P1 varchar(5), @P2 int) 
AS 
PRINT '>>'+ISNULL(@P1,'')+','+ISNULL(CONVERT(varchar(10),@P2),'') 
GO 

CREATE TABLE #Results (RowID int identity(1,1), Col1 varchar(5), Col2 int) 
DECLARE @Current int 
     ,@End  int 
DECLARE @Col1 varchar(5) 
     ,@Col2 int 


INSERT INTO #Results 
    (Col1, COl2) 
    EXEC nameofstoredprocedure_1 111, 222, 333 
SELECT @[email protected]@ROWCOUNT,@Current=0 

WHILE @Current<@End 
BEGIN 
    SET @[email protected]+1 

    SELECT 
     @Col1=COl1, @Col2=Col2 
     FROM #Results 
     WHERE [email protected] 

    EXEC nameofstoredprocedure_2 @Col1, @Col2 

END 

SALIDA:

(3 row(s) affected) 
>>AAA,111 
>>BBB,222 
>>CCC,333 
+0

cuando intenté esto con mi código, el ciclo nunca se ejecutó con 21 registros en #mytemp –

+0

Funciona para mí. entre 'SELECT @End = @@ ROWCOUNT, @ Current = 0' y' WHILE @Current <@ End' agregue esto: 'print 'procesará' + ISNULL (CONVERT (varchar (5), @ End), '') + 'rows'' y entre 'SET @ Current = @ Current + 1' y' SELECT ...'agregar esto:' print 'processing row' + ISNULL (CONVERT (varchar (5), @ Current), '') 'Además, si NO está poblando #Results con la inserción y ejecutando el WHILE al mismo tiempo, puede agregue esto, antes del tiempo: 'SELECT @ End = COUNT (*) FROM # Results' –

+0

los cursores son malos, publique su modificación de mi respuesta y le señalaré su error. Prefiero sacarme el ojo antes de usar el cursor. –

11

Pues es muy fácil de recorrer las filas en el procedimiento sql solo necesitas usar cursor, estoy dando que g un ejemplo aquí, por ello vamos a considerar un empleado de la tabla con la columna NOMBRE y EDAD con 50 registros en ella y u tiene que ejecutar un procedimiento almacenado decir TestProc que tendrá nombre y edad parámetros de cada fila.

create procedure CursorProc 
as 
begin 
    declare @count bigint; 
    declare @age varchar(500) 
    declare @name varchar(500) 
    select @count = (select count(*) from employee) 
    declare FirstCursor cursor for select name, age from employee 
    open FirstCursor 
    while @count > 0 
     begin 
     fetch FirstCursor into @name, @age 
     Exec TestProc @name, @age 
     set @count = @count - 1 
     end 
    close FirstCursor 
    deallocate FirstCursor 
end 

Asegúrese de desasignar el cursor para evitar errores.

+0

me salvaste el día. Mi primer procedimiento almacenado alguna vez :) – rajugaadu

Cuestiones relacionadas