Reputation: 2522
I’ve created a simple cursor in a stored procedure. The cursor simply iterates all the rows of a table.
From my output it seems that the iterator fetches n+1 rows.
I’ve tried a to break the while loop of the iteration but this doesn’t solve the issue. How come?
ALTER PROC spInsertNewCategory --spInsertNewCategory '-1','-1'
@categoryName NVARCHAR(80),
@categoryInfo NVARCHAR(80)
AS
BEGIN
DECLARE @siteLanguage_id INT
DECLARE @lang_id INT
DECLARE @default_siteLanguage INT
DECLARE cr_siteLanguage CURSOR
FOR
SELECT sl.siteLanguage_id, sl.lang_id, sl.default_siteLanguage
FROM siteLanguage sl
OPEN cr_siteLanguage
FETCH NEXT FROM cr_siteLanguage
INTO @siteLanguage_id,@lang_id,@default_siteLanguage
PRINT '@siteLanguage_id: '+ CAST(@siteLanguage_id AS NVARCHAR(3))+' fetch: '+ CAST(@@FETCH_STATUS AS NVARCHAR(5))
WHILE (@@FETCH_STATUS = 0)
BEGIN
IF (@@FETCH_STATUS=-1)
BEGIN
PRINT 'in if -1'
BREAK
END
FETCH NEXT FROM cr_siteLanguage
INTO @siteLanguage_id,@lang_id,@default_siteLanguage
PRINT '@siteLanguage_id: '+ CAST(@siteLanguage_id AS NVARCHAR(3))+' fetch: '+ CAST(@@FETCH_STATUS AS NVARCHAR(5))
END
CLOSE cr_siteLanguage
DEALLOCATE cr_siteLanguage
SELECT * FROM siteLanguage
END
Upvotes: 1
Views: 11696
Reputation: 45096
Yes it is stopping at @@FETCH_STATUS=-1
That is why you are not seeing your PRINT 'in if -1'
On the last FETCH @@FETCH_STATUS=-1 and it exits the WHILE (@@FETCH_STATUS = 0)
No it does not fetch n+1 rows.
On n+1 is when it knows there are no more rows.
The cursor does not know when it is the last row - it only know when there are no more rows (n+1)
That is why you fetch the first row before the loop
You print after the FETCH inside the loop
So you get that final -1
Then it drops out of the WHILE (@@FETCH_STATUS = 0)
Run it in debug and watch
OPEN cr_siteLanguage
FETCH NEXT FROM cr_siteLanguage
INTO @siteLanguage_id,@lang_id,@default_siteLanguage
WHILE (@@FETCH_STATUS = 0)
BEGIN
PRINT '@siteLanguage_id: '+ CAST(@siteLanguage_id AS NVARCHAR(3))+' fetch: '+ CAST(@@FETCH_STATUS AS NVARCHAR(5))
IF (@@FETCH_STATUS=-1)
BEGIN
PRINT 'in if -1'
BREAK
END
FETCH NEXT FROM cr_siteLanguage
INTO @siteLanguage_id,@lang_id,@default_siteLanguage
END
CLOSE cr_siteLanguage
DEALLOCATE cr_siteLanguage
Upvotes: 2
Reputation: 495
It appears that IF (@@FETCH_STATUS=-1)
will never be executed when @@FETCH_STATUS=-1,
You are checking the value of @@FETCH_STATUS immediately after entering the loop,
that has a WHERE clause (@@FETCH_STATUS = 0).
you could probably validate after the FETCH NEXT stmt inside the loop.
WHILE (@@FETCH_STATUS = 0)
BEGIN
FETCH NEXT FROM cr_siteLanguage
INTO @siteLanguage_id,@lang_id,@default_siteLanguage
PRINT '@siteLanguage_id: '+ CAST(@siteLanguage_id AS NVARCHAR(3))+' fetch: '+ CAST(@@FETCH_STATUS AS NVARCHAR(5))
IF (@@FETCH_STATUS=-1)
BEGIN
PRINT 'in if -1'
BREAK
END
END
Note: I assume the first FETCH NEXT stmt (immediately after OPEN cr_siteLanguage), does retrieve records.
Upvotes: 0