This flow shows how a cursor is declared, opened, rows fetched one by one, processed, then closed and deallocated.
Execution Sample
SQL
DECLARE emp_cursor CURSOR FOR SELECT id, name FROM employees;
OPEN emp_cursor;
FETCH NEXT FROM emp_cursor INTO @id, @name;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT CAST(@id ASVARCHAR) + ' ' + @name;
FETCH NEXT FROM emp_cursor INTO @id, @name;
END
CLOSE emp_cursor;
DEALLOCATE emp_cursor;
This code declares a cursor to select employee ids and names, then fetches and prints each row one by one.
Execution Table
Step
Action
Cursor State
Variables (@id, @name)
Output/Notes
1
DECLARE cursor emp_cursor
Declared, not open
NULL, NULL
Cursor ready for use
2
OPEN emp_cursor
Open, ready to fetch
NULL, NULL
Cursor opened on employees table
3
FETCH NEXT
Open, fetched first row
1, 'Alice'
First row fetched
4
Check @@FETCH_STATUS
0 (success)
1, 'Alice'
Continue loop
5
PRINT @id + ' ' + @name
Open
1, 'Alice'
Output: '1 Alice'
6
FETCH NEXT
Open, fetched second row
2, 'Bob'
Second row fetched
7
Check @@FETCH_STATUS
0 (success)
2, 'Bob'
Continue loop
8
PRINT @id + ' ' + @name
Open
2, 'Bob'
Output: '2 Bob'
9
FETCH NEXT
Open, fetched third row
3, 'Carol'
Third row fetched
10
Check @@FETCH_STATUS
0 (success)
3, 'Carol'
Continue loop
11
PRINT @id + ' ' + @name
Open
3, 'Carol'
Output: '3 Carol'
12
FETCH NEXT
Open, no more rows
NULL, NULL
No more rows
13
Check @@FETCH_STATUS
-1 (no data)
NULL, NULL
Exit loop
14
CLOSE emp_cursor
Closed
NULL, NULL
Cursor closed
15
DEALLOCATE emp_cursor
Deallocated
NULL, NULL
Cursor resources freed
💡 Loop ends when FETCH NEXT returns no more rows (@@FETCH_STATUS = -1)
Variable Tracker
Variable
Start
After Step 3
After Step 6
After Step 9
After Step 12
Final
@id
NULL
1
2
3
NULL
NULL
@name
NULL
'Alice'
'Bob'
'Carol'
NULL
NULL
@@FETCH_STATUS
NULL
0
0
0
-1
-1
Key Moments - 3 Insights
Why do we need to check @@FETCH_STATUS after each FETCH?
Because @@FETCH_STATUS tells us if the FETCH succeeded or if there are no more rows. Without checking, the loop might run forever or process invalid data. See execution_table rows 4, 7, 10, 13.
What happens if we forget to CLOSE or DEALLOCATE the cursor?
The cursor remains open and consumes resources, which can cause performance issues. Closing and deallocating frees those resources. See execution_table rows 14 and 15.
Why are variables @id and @name NULL after the last FETCH?
Because FETCH returns no data when rows are exhausted, so variables are set to NULL. This signals the end of data. See execution_table row 12.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what are the values of @id and @name after step 6?
A2, 'Bob'
B1, 'Alice'
C3, 'Carol'
DNULL, NULL
💡 Hint
Check the Variables column in execution_table row 6
At which step does the loop exit because there are no more rows?
AStep 15
BStep 10
CStep 13
DStep 9
💡 Hint
Look at the @@FETCH_STATUS value and loop exit note in execution_table rows 12 and 13
If we skip the CLOSE step, what happens to the cursor?
AIt deletes the data
BIt remains open and uses resources
CIt automatically closes
DIt fetches rows again
💡 Hint
Refer to key_moments about resource usage and execution_table row 14
Concept Snapshot
CURSOR usage in SQL:
1. DECLARE cursor for a SELECT query
2. OPEN cursor to start
3. FETCH rows one by one into variables
4. Check @@FETCH_STATUS to continue or stop
5. CLOSE cursor when done
6. DEALLOCATE cursor to free resources
Cursors let you process query results row-by-row.
Full Transcript
A cursor in SQL is a tool to process query results one row at a time. First, you DECLARE the cursor with a SELECT statement. Then you OPEN it to start reading. You FETCH each row into variables and check @@FETCH_STATUS to see if more rows exist. If yes, you process the row and FETCH the next. When no rows remain, you CLOSE and DEALLOCATE the cursor to free resources. This step-by-step process helps handle data row-wise instead of all at once.