I know that cursors are frowned upon and I try to avoid their use as much as possible, but there may be some legitimate reasons to use them. I have one and I am trying to use a pair of cursors: one for the primary table and one for the secondary table. The primary table cursor iterates through the primary table in an outer loop. the secondary table cursor iterates through the secondary table in the inner loop. The problem is, that the primary table cursor though apparently proceeding and saving the primary key column value [Fname] into a local variable @Fname, but it does not get the row for the corresponding foreign key column in the secondary table. For the secondary table it always returns the rows whose foreign key column value matches the primary key column value of the first row of the primary table.
Following is a very simplified example for what I want to do in the real stored procedure. Names is the primary table
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
Here is what I get for the result. Please note that for the outer loop it DOES show the up-to-date Fname, but when that Fname is used as @Fname to fetch the relevant row from the secondary table for the succeeding iterations, it still get the rows that match the first row (Bob) of the primary table.
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
Please let me know what am I do wrong. Thanks in advance!
The value of @fName is evaluated at :DECLARE curScores CURSOR and not in the primary loop. You must Declare and then deallocate the secon cursor in the primary loop.