Cursor (Transact‑SQL)
A cursor is a database object used to retrieve, manipulate, and navigate through a result set row by row. While set‑based operations are preferred for performance, cursors are useful when row‑by‑row processing is required.
Table of Contents
Syntax
DECLARE cursor_name CURSOR
[ LOCAL | GLOBAL ]
[ FORWARD_ONLY | SCROLL ]
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
[ TYPE_WARNING ]
FOR
select_statement
[ FOR UPDATE OF column_name [ ,...n ] ];
Example
This example demonstrates a simple forward‑only, read‑only cursor that iterates through employee records and prints each name.
USE AdventureWorks2019;
GO
DECLARE @EmployeeID INT, @FirstName NVARCHAR(50), @LastName NVARCHAR(50);
DECLARE emp_cursor CURSOR FAST_FORWARD FOR
SELECT BusinessEntityID, FirstName, LastName
FROM HumanResources.Employee AS e
JOIN Person.Person AS p
ON e.BusinessEntityID = p.BusinessEntityID
ORDER BY BusinessEntityID;
OPEN emp_cursor;
FETCH NEXT FROM emp_cursor INTO @EmployeeID, @FirstName, @LastName;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT CONCAT('ID: ', @EmployeeID, ' – ', @FirstName, ' ', @LastName);
FETCH NEXT FROM emp_cursor INTO @EmployeeID, @FirstName, @LastName;
END;
CLOSE emp_cursor;
DEALLOCATE emp_cursor;
Cursor Options
Option | Description |
---|---|
LOCAL / GLOBAL | Scope of the cursor (default is GLOBAL). |
FORWARD_ONLY | Only forward movement; higher performance. |
SCROLL | Allows backward movement. |
STATIC | Result set is a snapshot; does not reflect changes. |
KEYSET | Keys are fixed; data reflects changes to non‑key columns. |
DYNAMIC | Fully dynamic; reflects all changes. |
FAST_FORWARD | Read‑only, forward‑only, optimised for speed. |
READ_ONLY | Prevents updates through the cursor. |
SCROLL_LOCKS | Locks rows as they are fetched. |
OPTIMISTIC | Uses optimistic concurrency for updates. |
Performance Considerations
- Prefer set‑based operations whenever possible.
- Use
FAST_FORWARD
for read‑only, forward‑only tasks. - Keep the result set as small as feasible; filter in the SELECT.
- Avoid opening multiple cursors simultaneously.
- Remember to
CLOSE
andDEALLOCATE
each cursor to free resources.