Introduction
A cursor in SQL is a database object stored in temp memory and used to work with datasets. You can use cursors to manipulate data in a database, one row at a time. A cursor uses a SQL SELECT statement to fetch a rowset from a database and then can read and manipulate one row at a time.
Implicit vs explicit cursors
There are the following two types of cursors in SQL:
- Implicit Cursor
- Explicit Cursor
Implicit Cursor
The system generates and uses these types of cursors to manipulate a DML query (INSERT, UPDATE, and DELETE). In addition, a system also generates an implicit cursor when a SELECT command selects a single row.
Explicit Cursor
This type of cursor is generated by the user using a SELECT command. An explicit cursor contains more than one row, but only one row can be processed at a time. An explicit cursor moves one by one over the records. An explicit cursor uses a pointer that holds the record of a row. After fetching a row, the cursor pointer moves to the next row.
How to use a cursor in SQL?
To use a cursor, you must declare and execute a cursor. The process includes the following five steps.
- Declare Cursor: In this part, we declare variables and return a set of values.
- Open: This is the entering part of the cursor.
- Fetch: Used to retrieve the data row by row from a cursor.
- Close: This is an exit part of the cursor and is used to close a cursor.
- Deallocate: In this part, we delete the cursor definition and release all the system resources associated with the cursor.
Syntax
DECLARE @Variable nvarchar(50); -- Declare all required variables
DECLARE Cursor_Name CURSOR -- Declare Cursor Name
[LOCAL | GLOBAL] -- Define cursor scope
[FORWARD_ONLY | SCROLL] -- Define movement direction of cursor
[KEYSET | DYNAMIC | STATIC | FAST_FORWARD] -- Define basic type of cursor
[SCROLL_LOCKS | OPTIMISTIC | READ_ONLY] -- Define locks
OPEN Cursor_Name; -- Open cursor
FETCH NEXT FROM Cursor_Name; -- Fetch data from cursor
-- Implement SQL query
CLOSE Cursor_Name; -- Close the cursor
DEALLOCATE Cursor_Name; -- Deallocate all resources and memory.
Fetch data from a SQL cursor
The following are 6 methods for fetching data from a cursor in SQL
- FETCH NEXT retrieves the next row from the cursor's result set. It moves the cursor position forward by one row. In SQL Server, for example, you can use the FETCH NEXT statement to retrieve the next row.
- FETCH FIRST retrieves the first row from the cursor's result set. It is commonly used in combination with an ORDER BY clause to fetch the first row based on a specified sorting order.
- FETCH LAST retrieves the last row from the cursor's result set. Like FETCH FIRST, it is often used with an ORDER BY clause to fetch the last row based on a specific sorting order.
- FETCH PRIOR retrieves the row prior to the current cursor position. It moves the cursor backward by one row. FETCH PRIOR is useful when you need to traverse the result set in reverse order.
- FETCH ABSOLUTE retrieves a row from the cursor's result set at a specific position, regardless of the cursor's current position. It allows you to fetch a row by specifying an absolute row number.
- FETCH RELATIVE retrieves a row from the cursor's result set relative to the current cursor position. It allows you to fetch a row by specifying a relative position, such as moving forward or backward a certain number of rows from the current position.
Now we will explain four important terminologies of cursors.
Cursor Scope
Microsoft SQL Server supports the GLOBAL and LOCAL keywords on the DECLARE CURSOR statement to define the scope of the cursor name.
- GLOBAL - specifies that the cursor name is global to the connection.
- LOCAL - specifies that the cursor name is local to the Stored Procedure, trigger, or query that holds the cursor.
Data Fetch Option in Cursors
Microsoft SQL Server supports the following two fetch options for data:
- FORWARD_ONLY - Specifies that the cursor can only be scrolled from the first to the last row.
- SCROLL - It provides six options to fetch the data (FIRST, LAST, PRIOR, NEXT, RELATIVE, and ABSOLUTE).
Types of SQL Cursors
Microsoft SQL Server supports the following four types of cursors.
- STATIC CURSOR
A static cursor populates the result set during cursor creation, and the query result is cached for the lifetime of the cursor. A static cursor can move forward and backward. - FAST_FORWARD
This is the default type of cursor. It is identical to the static, except you can only scroll forward. - DYNAMIC
In a dynamic cursor, additions, and deletions are visible to others in the data source while the cursor is open. - KEYSET
This is similar to a dynamic cursor, except we can't see records others add. Likewise, if another user deletes a record, it is inaccessible from our recordset.
Types of locks on a Cursor
Locking is the process by which a DBMS restricts access to a row in a multi-user environment. When a row or column is exclusively locked, other users are not permitted to access the locked data until the lock is released. It is used for data integrity. This ensures that two users cannot simultaneously update the same column in a row.
Microsoft SQL Server supports the following three types of Locks.
- READ-ONLY
Specifies that the cursor cannot be updated. - SCROLL_LOCKS
Provides data integrity into the cursor. It specifies that the cursor will lock the rows as they are read into the cursor to ensure that updates or deletes made using the cursor will succeed. - OPTIMISTIC
Specifies that the cursor does not lock rows as they are read into the cursor. So, the updates or deletes made using the cursor will not succeed if the row has been updated outside the cursor.
First, we create a table as in the following,
CREATE TABLE [dbo].[Employee](
[Emp_ID] [int] NOT NULL,
[Emp_Name] [nvarchar](50) NOT NULL,
[Emp_Salary] [int] NOT NULL,
[Emp_City] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
(
[Emp_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Now insert some values into the table as in the following,
INSERT INTO Employee
SELECT 1, 'Pankaj', 25000, 'Alwar' UNION ALL
SELECT 2, 'Rahul', 26000, 'Alwar' UNION ALL
SELECT 3, 'Sandeep', 25000, 'Alwar' UNION ALL
SELECT 4, 'Sanjeev', 24000, 'Alwar' UNION ALL
SELECT 5, 'Neeraj', 28000, 'Alwar' UNION ALL
SELECT 6, 'Naru', 20000, 'Alwar' UNION ALL
SELECT 7, 'Omi', 23000, 'Alwar';
Select all values from the table as in the following,

Example 1
SET NOCOUNT ON;
DECLARE @EMP_ID INT;
DECLARE @EMP_NAME NVARCHAR(MAX);
DECLARE @EMP_SALARY INT;
DECLARE @EMP_CITY NVARCHAR(MAX);
DECLARE EMP_CURSOR CURSOR
LOCAL FORWARD_ONLY FOR
SELECT * FROM Employee;
OPEN EMP_CURSOR;
FETCH NEXT FROM EMP_CURSOR INTO @EMP_ID, @EMP_NAME, @EMP_SALARY, @EMP_CITY;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'EMP_ID: ' + CONVERT(NVARCHAR(MAX), @EMP_ID) + ' EMP_NAME ' + @EMP_NAME + ' EMP_SALARY ' + CONVERT(NVARCHAR(MAX), @EMP_SALARY) + ' EMP_CITY ' + @EMP_CITY;
FETCH NEXT FROM EMP_CURSOR INTO @EMP_ID, @EMP_NAME, @EMP_SALARY, @EMP_CITY;
END;
CLOSE EMP_CURSOR;
DEALLOCATE EMP_CURSOR;
Output








Nikunj SatasiyaPosted Feb 28, 2019, 4:23 AM
Nice Explanation....
Shuvo SarkerPosted Dec 27, 2016, 6:24 AM
Good job.really helpful for practical work.
Yashwanth MuthineniPosted Aug 27, 2015, 5:56 AM
Nice Share
Santhakumar MunuswamyPosted Jun 6, 2015, 2:45 AM
Thanks for nice article
Pankaj Kumar ChoudharyPosted Jun 4, 2015, 10:45 AM
Thanks @Nitin sir........
NitinPosted Jun 4, 2015, 9:41 AM
nice
Sibeesh VenuPosted Jun 4, 2015, 8:10 AM
Good one.
Gakenh01Posted Jun 4, 2015, 7:26 AM
Nice comprehensive write-up.