Как я могу перебирать набор записей в хранимой процедуре?

Мне нужно перебрать набор записей из хранимой процедуры и выполнить другую хранимую процедуру, используя все поля в качестве аргументов. Я не могу завершить эту итерацию в коде. Я нашел образцы в интернетах, но все они, похоже, имеют дело с прилавком. Я не уверен, что у моей проблемы был счетчик. Мне нужен эквивалент T-SQL foreach

В настоящее время моя первая хранимая процедура сохраняет свой набор записей в таблице temp, #mytemp. Я предполагаю, что я вызову вторичную хранимую процедуру следующим образом:

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

Ответ 1

Вам нужно создать курсор для циклического набора записей.

Пример таблицы:

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')

Курсор:

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

Вот ссылка на MSDN о том, как их создавать.

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

Вот почему я использовал Raise Error вместо PRINT для вывода.
http://structuredsight.com/2014/11/24/wait-wait-dont-tell-me-on-second-thought/

Ответ 2

Ну его очень легко перебрать по строкам в sql-процедуре, вам просто нужно использовать курсор, здесь я приведу пример, потому что мы рассмотрим таблицу Сотрудник со столбцом NAME и AGE с 50 записями, и вам нужно выполнить хранимую процедуру: TESTPROC, которая будет принимать параметры имени и возраста каждой строки.

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

Убедитесь, что вы удалите курсор, чтобы избежать ошибок.

Ответ 3

попробуйте это (курсор свободного цикла):

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

рабочий пример:

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

ВЫВОД:

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