A Cursor allow us to retrieve data from a result
set in singleton fashion means row by row. Cursor are required when we
need to update records in a database table one row at a time.
A
Cursor impacts the performance of the SQL Server since it uses the SQL
Server instances' memory, reduce concurrency, decrease network bandwidth
and lock resources. Hence it is mandatory to understand the cursor
types and its functions so that you can use suitable cursor according to
your needs.
You should avoid the use of cursor. Basically you
should use cursor alternatives like as WHILE loop, sub queries,
Temporary tables and Table variables. We should use cursor in that case
when there is no option except cursor.
Cursor is a database objects to retrieve data from a
result set one row at a time, instead of the T-SQL commands that
operate on all the rows in the result set at one time. We use cursor
when we need to update records in a database table in singleton fashion
means row by row.
Life Cycle of Cursor
-
Declare Cursor
A cursor is declared by defining the SQL statement that returns a result set.
-
Open
A Cursor is opened and populated by executing the SQL statement defined by the cursor.
-
Fetch
When cursor is opened, rows can be fetched from the cursor one by one or in a block to do data manipulation.
-
Close
After data manipulation, we should close the cursor explicitly.
-
Deallocate
Finally, we need to delete the cursor definition and released all the system resources associated with the cursor.
Simple Exp .
declare @BrhCode varchar(5)
declare @BrhName varchar(50)
DECLARE TBName CURSOR
For
select BrhCode,BrhName from branch_master
Open TBName
FETCH NEXT FROM TBName into @BrhCode,@BrhName
WHILE @@FETCH_STATUS = 0
BEGIN
--print @BrhCode
Insert into user_module_Detail values('Renewal Receipt', @BrhCode,'Transaction','A')
FETCH NEXT FROM TBName into @BrhCode,@BrhName
END
CLOSE TBName
DEALLOCATE TBName
Types of Cursors
- Static Cursors
A
static cursor populates the result set at the time of cursor creation
and query result is cached for the lifetime of the cursor. A static
cursor can move forward and backward direction. A static cursor is
slower and use more memory in comparison to other cursor. Hence you
should use it only if scrolling is required and other types of cursors
are not suitable.
You can't update, delete data using static
cursor. It is not sensitive to any changes to the original data source.
By default static cursors are scrollable.
Dynamic Cursors
A
dynamic cursor allows you to see the data updation, deletion and
insertion in the data source while the cursor is open. Hence a dynamic
cursor is sensitive to any changes to the data source and supports
update, delete operations. By default dynamic cursors are scrollable.
Forward Only Cursors
A
forward only cursor is the fastest cursor among the all cursors but it
doesn't support backward scrolling. You can update, delete data using
Forward Only cursor. It is sensitive to any changes to the original data
source.
There are three more types of Forward Only Cursors.Forward_Only KEYSET, FORWARD_ONLY STATIC and FAST_FORWARD.
A FORWARD_ONLY STATIC Cursor
is populated at the time of creation and cached the data to the cursor
lifetime. It is not sensitive to any changes to the data source.
A FAST_FORWARD Cursor is the fastest cursor and it is not sensitive to any changes to the data source.
Keyset Driven Cursors
A
keyset driven cursor is controlled by a set of unique identifiers as
the keys in the keyset. The keyset depends on all the rows that
qualified the SELECT statement at the time of cursor was opened. A
keyset driven cursor is sensitive to any changes to the data source and
supports update, delete operations. By default keyset driven cursors are
scrollable.
SQL SERVER – Examples of Cursors
- CREATE TABLE Employee
- (
- EmpID int PRIMARY KEY,
- EmpName varchar (50) NOT NULL,
- Salary int NOT NULL,
- Address varchar (200) NOT NULL,
- )
- GO
- INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(1,'Mohan',12000,'Noida')
- INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(2,'Pavan',25000,'Delhi')
- INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(3,'Amit',22000,'Dehradun')
- INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(4,'Sonu',22000,'Noida')
- INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(5,'Deepak',28000,'Gurgaon')
- GO
- SELECT * FROM Employee
Static Cursor - Example
- SET NOCOUNT ON
- DECLARE @Id int
- DECLARE @name varchar(50)
- DECLARE @salary int
- DECLARE cur_emp CURSOR
- STATIC FOR
- SELECT EmpID,EmpName,Salary from Employee
- OPEN cur_emp
- IF @@CURSOR_ROWS > 0
- BEGIN
- FETCH NEXT FROM cur_emp INTO @Id,@name,@salary
- WHILE @@Fetch_status = 0
- BEGIN
- PRINT 'ID : '+ convert(varchar(20),@Id)+', Name : '+@name+ ', Salary : '+convert(varchar(20),@salary)
- FETCH NEXT FROM cur_emp INTO @Id,@name,@salary
- END
- END
- CLOSE cur_emp
- DEALLOCATE cur_emp
- SET NOCOUNT OFF
Dynamic Cursor - Example
- --Dynamic Cursor for Update
- SET NOCOUNT ON
- DECLARE @Id int
- DECLARE @name varchar(50)
- DECLARE Dynamic_cur_empupdate CURSOR
- DYNAMIC
- FOR
- SELECT EmpID,EmpName from Employee ORDER BY EmpName
- OPEN Dynamic_cur_empupdate
- IF @@CURSOR_ROWS > 0
- BEGIN
- FETCH NEXT FROM Dynamic_cur_empupdate INTO @Id,@name
- WHILE @@Fetch_status = 0
- BEGIN
- IF @name='Mohan'
- Update Employee SET Salary=15000 WHERE CURRENT OF Dynamic_cur_empupdate
- FETCH NEXT FROM Dynamic_cur_empupdate INTO @Id,@name
- END
- END
- CLOSE Dynamic_cur_empupdate
- DEALLOCATE Dynamic_cur_empupdate
- SET NOCOUNT OFF
- Go
- Select * from Employee
- -- Dynamic Cursor for DELETE
- SET NOCOUNT ON
- DECLARE @Id int
- DECLARE @name varchar(50)
- DECLARE Dynamic_cur_empdelete CURSOR
- DYNAMIC
- FOR
- SELECT EmpID,EmpName from Employee ORDER BY EmpName
- OPEN Dynamic_cur_empdelete
- IF @@CURSOR_ROWS > 0
- BEGIN
- FETCH NEXT FROM Dynamic_cur_empdelete INTO @Id,@name
- WHILE @@Fetch_status = 0
- BEGIN
- IF @name='Deepak'
- DELETE Employee WHERE CURRENT OF Dynamic_cur_empdelete
- FETCH NEXT FROM Dynamic_cur_empdelete INTO @Id,@name
- END
- END
- CLOSE Dynamic_cur_empdelete
- DEALLOCATE Dynamic_cur_empdelete
- SET NOCOUNT OFF
- Go
- Select * from Employee
Forward Only Cursor - Example
- --Forward Only Cursor for Update
- SET NOCOUNT ON
- DECLARE @Id int
- DECLARE @name varchar(50)
- DECLARE Forward_cur_empupdate CURSOR
- FORWARD_ONLY
- FOR
- SELECT EmpID,EmpName from Employee ORDER BY EmpName
- OPEN Forward_cur_empupdate
- IF @@CURSOR_ROWS > 0
- BEGIN
- FETCH NEXT FROM Forward_cur_empupdate INTO @Id,@name
- WHILE @@Fetch_status = 0
- BEGIN
- IF @name='Amit'
- Update Employee SET Salary=24000 WHERE CURRENT OF Forward_cur_empupdate
- FETCH NEXT FROM Forward_cur_empupdate INTO @Id,@name
- END
- END
- CLOSE Forward_cur_empupdate
- DEALLOCATE Forward_cur_empupdate
- SET NOCOUNT OFF
- Go
- Select * from Employee
- -- Forward Only Cursor for Delete
- SET NOCOUNT ON
- DECLARE @Id int
- DECLARE @name varchar(50)
- DECLARE Forward_cur_empdelete CURSOR
- FORWARD_ONLY
- FOR
- SELECT EmpID,EmpName from Employee ORDER BY EmpName
- OPEN Forward_cur_empdelete
- IF @@CURSOR_ROWS > 0
- BEGIN
- FETCH NEXT FROM Forward_cur_empdelete INTO @Id,@name
- WHILE @@Fetch_status = 0
- BEGIN
- IF @name='Sonu'
- DELETE Employee WHERE CURRENT OF Forward_cur_empdelete
- FETCH NEXT FROM Forward_cur_empdelete INTO @Id,@name
- END
- END
- CLOSE Forward_cur_empdelete
- DEALLOCATE Forward_cur_empdelete
- SET NOCOUNT OFF
- Go
- Select * from Employee
Keyset Driven Cursor - Example
- -- Keyset driven Cursor for Update
- SET NOCOUNT ON
- DECLARE @Id int
- DECLARE @name varchar(50)
- DECLARE Keyset_cur_empupdate CURSOR
- KEYSET
- FOR
- SELECT EmpID,EmpName from Employee ORDER BY EmpName
- OPEN Keyset_cur_empupdate
- IF @@CURSOR_ROWS > 0
- BEGIN
- FETCH NEXT FROM Keyset_cur_empupdate INTO @Id,@name
- WHILE @@Fetch_status = 0
- BEGIN
- IF @name='Pavan'
- Update Employee SET Salary=27000 WHERE CURRENT OF Keyset_cur_empupdate
- FETCH NEXT FROM Keyset_cur_empupdate INTO @Id,@name
- END
- END
- CLOSE Keyset_cur_empupdate
- DEALLOCATE Keyset_cur_empupdate
- SET NOCOUNT OFF
- Go
- Select * from Employee
- -- Keyse Driven Cursor for Delete
- SET NOCOUNT ON
- DECLARE @Id int
- DECLARE @name varchar(50)
- DECLARE Keyset_cur_empdelete CURSOR
- KEYSET
- FOR
- SELECT EmpID,EmpName from Employee ORDER BY EmpName
- OPEN Keyset_cur_empdelete
- IF @@CURSOR_ROWS > 0
- BEGIN
- FETCH NEXT FROM Keyset_cur_empdelete INTO @Id,@name
- WHILE @@Fetch_status = 0
- BEGIN
- IF @name='Amit'
- DELETE Employee WHERE CURRENT OF Keyset_cur_empdelete
- FETCH NEXT FROM Keyset_cur_empdelete INTO @Id,@name
- END
- END
- CLOSE Keyset_cur_empdelete
- DEALLOCATE Keyset_cur_empdelete
- SET NOCOUNT OFF
- Go Select * from Employee