Я знаю, что курсоры не одобряются, и я стараюсь максимально избегать их использования, но могут быть некоторые законные причины для их использования. У меня есть один, и я пытаюсь использовать пару курсоров: один для основной таблицы и один для дополнительной таблицы. Курсор первичной таблицы перебирает первичную таблицу во внешнем цикле. курсор вторичной таблицы перебирает вторичную таблицу во внутреннем цикле.
Проблема заключается в том, что курсор первичной таблицы, по-видимому, продолжает и сохраняет значение столбца первичного ключа [Fname] в локальной переменной @Fname, но не получает строку для соответствующего столбца внешнего ключа во вторичной таблице. Для вторичной таблицы она всегда возвращает строки, значение столбца внешнего ключа которых совпадает со значением столбца первичного ключа первая строка первичной таблицы.
Ниже приведен очень упрощенный пример того, что я хочу сделать в реальной хранимой процедуре.
Имена первичной таблицы
SET NOCOUNT ON
DECLARE
@Fname varchar(50) -- to hold the fname column value from outer cursor loop
,@FK_Fname varchar(50) -- to hold the fname column value from inner cursor loop
,@score int
;
--prepare primary table to be iterated in the outer loop
DECLARE @Names AS Table (Fname varchar(50))
INSERT @Names
SELECT 'Jim' UNION
SELECT 'Bob' UNION
SELECT 'Sam' UNION
SELECT 'Jo'
--prepare secondary/detail table to be iterated in the inner loop
DECLARE @Scores AS Table (Fname varchar(50), Score int)
INSERT @Scores
SELECT 'Jo',1 UNION
SELECT 'Jo',5 UNION
SELECT 'Jim',4 UNION
SELECT 'Bob',10 UNION
SELECT 'Bob',15
--cursor to iterate on the primary table in the outer loop
DECLARE curNames CURSOR
FOR SELECT Fname FROM @Names
OPEN curNames
FETCH NEXT FROM curNames INTO @Fname
--cursor to iterate on the secondary table in the inner loop
DECLARE curScores CURSOR
FOR
SELECT FName,Score
FROM @Scores
WHERE Fname = @Fname
--*** NOTE: Using the primary table's column value @Fname from the outer loop
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Outer loop @Fname = ' + @Fname
OPEN curScores
FETCH NEXT FROM curScores INTO @FK_Fname, @Score
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT ' FK_Fname=' + @FK_Fname + '. Score=' + STR(@Score)
FETCH NEXT FROM curScores INTO @FK_Fname, @Score
END
CLOSE curScores
FETCH NEXT FROM curNames INTO @Fname
END
DEALLOCATE curScores
CLOSE curNames
DEALLOCATE curNames
Вот что я получаю за результат. Обратите внимание, что для внешнего цикла он показывает актуальное имя Fname, но когда это имя Fname используется как @Fname для извлечения соответствующей строки из вторичной таблицы для последующих итераций, он все равно получает строки, соответствующие первому строка (Bob) первичной таблицы.
Outer loop @Fname = Bob
FK_Fname=Bob. Score=10
FK_Fname=Bob. Score=15
Outer loop @Fname = Jim
FK_Fname=Bob. Score=10
FK_Fname=Bob. Score=15
Outer loop @Fname = Jo
FK_Fname=Bob. Score=10
FK_Fname=Bob. Score=15
Outer loop @Fname = Sam
FK_Fname=Bob. Score=10
FK_Fname=Bob. Score=15
Пожалуйста, дайте мне знать, что я делаю не так.
Заранее спасибо!