Sunday 4 January 2015

Cursor

  • Allows row-by-row processing. Control will be with user rather than SQL server
  • Different options can be applied while creating a cursor
o Local/global
o Static/dynamic/fast_forward/ketyset driven
o Forward_only/scroll
  • Generally it should be avoided as it is affecting a performance a big time
  • If another SP is being called within cursor, it will fail. So while loop should be used instead of cursor
  • A general syntax
DECLARE cur CURSOR
FOR SELECT a,FROM TableName
OPEN cur
FETCH NEXT FROM Cur INTO @a, @b
WHILE @@FETCH_STATUS = 0
BEGIN
-- Your logic
FETCH NEXT FROM Cur INTO @a, @b
END
CLOSE cur
DEALLOCATE cur
  • In some cases, Cursor will be faster than normal join e.g. 
    • when there is some N level of parent-child relationship than rather than joining the same table multiple times, we can use cursor and achieve the results fast
    • When you have to insert millions of record in one table then probably you can start cursor and insert a bunch of records (let's say 25K records) in chunks which will be faster than a single INSERT statement
  • Even if we have to use cursor, it is recommended that we use WHILE LOOP rather than using cursor

Keyset-Driven Cursor


Introduction
In this article I describe keyset-driven cursor. With the help of keyset-drivin cursor we can find  first, next, last and any specific row of the table.
First we create a table named emp to apply a cursor on this table:
Creation of table
create table emp(emp_id int,em_name varchar(10))
go 
insert into emp
select 1,'d' union all
select 2,'e' union all
select 3,'f' union all
select 4,'mahi' union all
select 5,'gill' union all
select 6,'singh'
go
select * from emp
Output:
cursor-in-sql.jpg
Keyset-driven cursor:
It lies between a static and a dynamic cursor. When we open keyset-drivin cursor than it saves the list of unique values for the entire result set, these values are called keyset. These keys retrieve the current data values for each row.
Creation of Keyset-drivin cursor:
declare key_cursor cursor
keyset for 
select * from emp

Opening of Keyset-drivin cursor:
We open a Keyset-drivin Cursor as in the in following:
open key_cursor
Fetching first data from Keyset-drivin Cursor:
fetch firstfrom key_cursor
Outout:
keyDriven-cursor-in-sql-server-first1.jpg
Closing the Keyset-drivin Cursor:
We close Keyset-drivin Cursor as in the following
close key_cursor
Dealloting Keyset-drivin Cursor:
We deallocate Keyset-drivin Cursor as following

SQL SERVER – Examples of Cursors

  1. CREATE TABLE Employee
  2. (
  3. EmpID int PRIMARY KEY,
  4. EmpName varchar (50) NOT NULL,
  5. Salary int NOT NULL,
  6. Address varchar (200) NOT NULL,
  7. )
  8. GO
  9. INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(1,'Mohan',12000,'Noida')
  10. INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(2,'Pavan',25000,'Delhi')
  11. INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(3,'Amit',22000,'Dehradun')
  12. INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(4,'Sonu',22000,'Noida')
  13. INSERT INTO Employee(EmpID,EmpName,Salary,Address) VALUES(5,'Deepak',28000,'Gurgaon')
  14. GO
  15. SELECT * FROM Employee

Static Cursor - Example

  1. SET NOCOUNT ON
  2. DECLARE @Id int
  3. DECLARE @name varchar(50)
  4. DECLARE @salary int
  5. DECLARE cur_emp CURSOR
  6. STATIC FOR
  7. SELECT EmpID,EmpName,Salary from Employee
  8. OPEN cur_emp
  9. IF @@CURSOR_ROWS > 0
  10. BEGIN
  11. FETCH NEXT FROM cur_emp INTO @Id,@name,@salary
  12. WHILE @@Fetch_status = 0
  13. BEGIN
  14. PRINT 'ID : '+ convert(varchar(20),@Id)+', Name : '+@name+ ', Salary : '+convert(varchar(20),@salary)
  15. FETCH NEXT FROM cur_emp INTO @Id,@name,@salary
  16. END
  17. END
  18. CLOSE cur_emp
  19. DEALLOCATE cur_emp
  20. SET NOCOUNT OFF

Dynamic Cursor - Example

  1. --Dynamic Cursor for Update
  2. SET NOCOUNT ON
  3. DECLARE @Id int
  4. DECLARE @name varchar(50)
  5. DECLARE Dynamic_cur_empupdate CURSOR
  6. DYNAMIC
  7. FOR
  8. SELECT EmpID,EmpName from Employee ORDER BY EmpName
  9. OPEN Dynamic_cur_empupdate
  10. IF @@CURSOR_ROWS > 0
  11. BEGIN
  12. FETCH NEXT FROM Dynamic_cur_empupdate INTO @Id,@name
  13. WHILE @@Fetch_status = 0
  14. BEGIN
  15. IF @name='Mohan'
  16. Update Employee SET Salary=15000 WHERE CURRENT OF Dynamic_cur_empupdate
  17. FETCH NEXT FROM Dynamic_cur_empupdate INTO @Id,@name
  18. END
  19. END
  20. CLOSE Dynamic_cur_empupdate
  21. DEALLOCATE Dynamic_cur_empupdate
  22. SET NOCOUNT OFF
  23. Go
  24. Select * from Employee
  1. -- Dynamic Cursor for DELETE
  2. SET NOCOUNT ON
  3. DECLARE @Id int
  4. DECLARE @name varchar(50)
  5. DECLARE Dynamic_cur_empdelete CURSOR
  6. DYNAMIC
  7. FOR
  8. SELECT EmpID,EmpName from Employee ORDER BY EmpName
  9. OPEN Dynamic_cur_empdelete
  10. IF @@CURSOR_ROWS > 0
  11. BEGIN
  12. FETCH NEXT FROM Dynamic_cur_empdelete INTO @Id,@name
  13. WHILE @@Fetch_status = 0
  14. BEGIN
  15. IF @name='Deepak'
  16. DELETE Employee WHERE CURRENT OF Dynamic_cur_empdelete
  17. FETCH NEXT FROM Dynamic_cur_empdelete INTO @Id,@name
  18. END
  19. END
  20. CLOSE Dynamic_cur_empdelete
  21. DEALLOCATE Dynamic_cur_empdelete
  22. SET NOCOUNT OFF
  23. Go
  24. Select * from Employee

Forward Only Cursor - Example

  1. --Forward Only Cursor for Update
  2. SET NOCOUNT ON
  3. DECLARE @Id int
  4. DECLARE @name varchar(50)
  5. DECLARE Forward_cur_empupdate CURSOR
  6. FORWARD_ONLY
  7. FOR
  8. SELECT EmpID,EmpName from Employee ORDER BY EmpName
  9. OPEN Forward_cur_empupdate
  10. IF @@CURSOR_ROWS > 0
  11. BEGIN
  12. FETCH NEXT FROM Forward_cur_empupdate INTO @Id,@name
  13. WHILE @@Fetch_status = 0
  14. BEGIN
  15. IF @name='Amit'
  16. Update Employee SET Salary=24000 WHERE CURRENT OF Forward_cur_empupdate
  17. FETCH NEXT FROM Forward_cur_empupdate INTO @Id,@name
  18. END
  19. END
  20. CLOSE Forward_cur_empupdate
  21. DEALLOCATE Forward_cur_empupdate
  22. SET NOCOUNT OFF
  23. Go
  24. Select * from Employee
  1. -- Forward Only Cursor for Delete
  2. SET NOCOUNT ON
  3. DECLARE @Id int
  4. DECLARE @name varchar(50)
  5. DECLARE Forward_cur_empdelete CURSOR
  6. FORWARD_ONLY
  7. FOR
  8. SELECT EmpID,EmpName from Employee ORDER BY EmpName
  9. OPEN Forward_cur_empdelete
  10. IF @@CURSOR_ROWS > 0
  11. BEGIN
  12. FETCH NEXT FROM Forward_cur_empdelete INTO @Id,@name
  13. WHILE @@Fetch_status = 0
  14. BEGIN
  15. IF @name='Sonu'
  16. DELETE Employee WHERE CURRENT OF Forward_cur_empdelete
  17. FETCH NEXT FROM Forward_cur_empdelete INTO @Id,@name
  18. END
  19. END
  20. CLOSE Forward_cur_empdelete
  21. DEALLOCATE Forward_cur_empdelete
  22. SET NOCOUNT OFF
  23. Go
  24. Select * from Employee

Keyset Driven Cursor - Example

  1. -- Keyset driven Cursor for Update
  2. SET NOCOUNT ON
  3. DECLARE @Id int
  4. DECLARE @name varchar(50)
  5. DECLARE Keyset_cur_empupdate CURSOR
  6. KEYSET
  7. FOR
  8. SELECT EmpID,EmpName from Employee ORDER BY EmpName
  9. OPEN Keyset_cur_empupdate
  10. IF @@CURSOR_ROWS > 0
  11. BEGIN
  12. FETCH NEXT FROM Keyset_cur_empupdate INTO @Id,@name
  13. WHILE @@Fetch_status = 0
  14. BEGIN
  15. IF @name='Pavan'
  16. Update Employee SET Salary=27000 WHERE CURRENT OF Keyset_cur_empupdate
  17. FETCH NEXT FROM Keyset_cur_empupdate INTO @Id,@name
  18. END
  19. END
  20. CLOSE Keyset_cur_empupdate
  21. DEALLOCATE Keyset_cur_empupdate
  22. SET NOCOUNT OFF
  23. Go
  24. Select * from Employee
  1. -- Keyse Driven Cursor for Delete
  2. SET NOCOUNT ON
  3. DECLARE @Id int
  4. DECLARE @name varchar(50)
  5. DECLARE Keyset_cur_empdelete CURSOR
  6. KEYSET
  7. FOR
  8. SELECT EmpID,EmpName from Employee ORDER BY EmpName
  9. OPEN Keyset_cur_empdelete
  10. IF @@CURSOR_ROWS > 0
  11. BEGIN
  12. FETCH NEXT FROM Keyset_cur_empdelete INTO @Id,@name
  13. WHILE @@Fetch_status = 0
  14. BEGIN
  15. IF @name='Amit'
  16. DELETE Employee WHERE CURRENT OF Keyset_cur_empdelete
  17. FETCH NEXT FROM Keyset_cur_empdelete INTO @Id,@name
  18. END
  19. END
  20. CLOSE Keyset_cur_empdelete
  21. DEALLOCATE Keyset_cur_empdelete
  22. SET NOCOUNT OFF
  23. Go Select * from Employee

No comments:

Post a Comment