Build your professional network on facebook via our app Go to app
 
 
 
Industry : IT Services Functional Area : Architecture
Activity:  4 comments  426 views  last activity : 07 06 2010 20:18:04 +0000
 Refer 35
Share
 
 
 

Avoid Cursors 

There may be times when you need to loop through a resultset a row at a time and perform a certain action for each row. The most obvious way to solve this task is to use a SQL Cursor.

Whilst cursors may seem like a good idea they can often cause your database application problems as they can lock the tables that are used to populate the cursor whilst the rows in the cursor are looped through. Depending on the action that you are performing on each row this can take a considerable time. The effect of this is that tables cannot be updated or accessed by other users whilst the cursor is open.

Lots of articles have beaten up on SQL Server cursors -- database objects that manipulate data in a set on a row-by-row basis. I wish cursors had never been introduced. But, unfortunately, cursors are a fact of life. Problems with cursors include extending locks, their inability to cache execution plans and CPU/RAM overhead. Many T-SQL programmers and DBAs use the cursors in their code knowingly or un-knowingly. They do not know how to successfully loop over records without the need for cursors. In this tip,

Some alternatives to cursors that provide looping functionality.


Method 1: Temp table with identity column

In the first approach, we can use a temp table with an identity column added to allow for row-by-row selection. If you're performing an INSERT/UPDATE/DELETE, be sure to use the explicit transactions. This vastly reduces the load on your log file by committing per loop, and it prevents huge rollbacks in the case of failure.


-- Create a temporary table, note the IDENTITY
-- column that will be used to loop through
-- the rows of this table
CREATE TABLE #ActiveEmployee (
 RowID int IDENTITY(1, 1),
 EmployeeID int,
 FirstName varchar(30),
 LastName varchar(30)
)
DECLARE @NumberRecords int, @RowCount int
DECLARE @EmployeeID int, @FirstName varchar(30), @LastName varchar(30)

-- Insert the resultset we want to loop through
-- into the temporary table
INSERT INTO #ActiveEmployee (EmployeeID, FirstName, LastName)
SELECT EmployeeID, FirstName, LastName
FROM Employee
WHERE Active = 1

-- Get the number of records in the temporary table
SET @NumberRecords = @@ROWCOUNT
SET @RowCount = 1


create clustered index idx_tmp on #ActiveEmployee(RowID) WITH FILLFACTOR = 100

/*

Always do this after the insert, since it's faster to add the index in bulk than to update the index as you write into the temp table. Since you know the data in this column, you can set the fill factor to 100% to get the best read times.

*/

-- loop through all records in the temporary table
-- using the WHILE loop construct
WHILE @RowCount <= @NumberRecords
BEGIN
 SELECT @EmployeeID = EmployeeID, @FirstName = FirstName, @LastName = LastName
 FROM #ActiveCustomer
 WHERE RowID = @RowCount


EXEC MyStoredProc @EmployeeID, @FirstName, @LastName

 SET @RowCount = @RowCount + 1
END

-- drop the temporary table
DROP TABLE #ActiveEmployee


This gives us the benefits that the Customer table is not locked as we are looping through our resultset so other queries on the Customer table that are submitted by other users will execute much faster. We will also have a faster operating SQL script by avoiding cursors which are slow in themselves.


Method 2: Temp table without ID

In the second approach, we use a temp table without an identity column and simply grab the top row to process, then loop until we find no more rows to process. If you're performing an INSERT/UPDATE/DELETE, again, be sure to use the explicit transactions to vastly reduce the load on your log file by committing per loop, which prevents huge rollbacks in the case of failure.

set nocount on

declare @i int --iterator
declare @iRwCnt int --rowcount
declare @sValue varchar(100)
set @i = 1 --initialize

create table #tbl(Value varchar(100))

insert into #tbl(Value)
select name
from master..sysdatabases (nolock)

set @iRwCnt = @@ROWCOUNT --SCOPE_IDENTITY() would also work

create clustered index idx_tmp on #tbl(Value) WITH FILLFACTOR = 100
/*

Always do this after the insert, since it's faster to add the index in bulk than to update the index as you write into the temp table. Since you know the data in this column, you can set the fill factor to 100% to get the best read times.

*/

while @iRwCnt > 0
begin
select top 1 @sValue = Value from #tbl
set @iRwCnt = @@ROWCOUNT --ensure that we still have data

if @iRwCnt > 0
begin

--begin tran
print 'My Value is ' + @sValue --replace with your operations on this value
--commit tran

delete from #tbl where value = @sValue --remove processed record
end
end

drop table #tbl


This article gives you some good reasons why cursors in SQL Server should be avoided as well as some alternatives that give you looping functionality. Keep in mind that SQL Server is designed around batch processing, so the less you loop, the faster your system will run.

 Top Comment : Harshil Shukla   | 12 06 2008 05:32:27 +0000
Thanks for sharing and nice work you did but I have some concerns regarding using loops for any operation for stored procedure and SELECT command is used. I think so if we use SELECT command in a loop then whether we use CURSOR or not it will be same. Execution of SELECT command will take considerable time and also assigning values will take time of CPU and RAM. Also you have used Temporary table, overhead of creating a temporary table is also on CPU and RAM but also maintaining it. I think so there must be an optional use of cursor which can minimize the usage of CPU and RAM also CURSORs stores value whenever they are created and opened. And after that it's executions is fast. No doubt the overhead is on CPU and RAM while declaring. And yes it is also big overhead to deallocate and close the same. My Dear friend do not take this in other way but I am trying to give other ideas which can be useful, I have also removed some of the cursors in my project which was using maximum time. Again thanks for sharing such a good information. Keep it up.
 
4 comments on "Avoid Cursors"
  Commented by  Bellala Gopinatha Rao, Project Manager Promax Management Consultants    | 01 03 2009 12:41:27 +0000
good one thanks
  Commented by  Harshil Shukla, Software Developer, Gateway Technolabs Pvt. Ltd    | 12 06 2008 05:32:27 +0000
Rating : +1 
Thanks for sharing and nice work you did but I have some concerns regarding using loops for any operation for stored procedure and SELECT command is used. I think so if we use SELECT command in a loop then whether we use CURSOR or not it will be same. Execution of SELECT command will take considerable time and also assigning values will take time of CPU and RAM. Also you have used Temporary table, overhead of creating a temporary table is also on CPU and RAM but also maintaining it. I think so there must be an optional use of cursor which can minimize the usage of CPU and RAM also CURSORs stores value whenever they are created and opened. And after that it's executions is fast. No doubt the overhead is on CPU and RAM while declaring. And yes it is also big overhead to deallocate and close the same. My Dear friend do not take this in other way but I am trying to give other ideas which can be useful, I have also removed some of the cursors in my project which was using maximum time. Again thanks for sharing such a good information. Keep it up.
  Commented by  Vijayanand Kuppurao, Software Developer Vigna Systems    | 12 05 2008 11:20:02 +0000
Good One
  Commented by  japi, HR Manager, ACME Consultants    | 11 28 2008 03:29:28 +0000
thanks for sharing
Add your comment on "Avoid Cursors"

Rate:
Submit
Leading Recruitment Firm
Leading Recruitment Firm
Viewers also viewed
Tips for avoid sleepiness During the Day at work
 
371 referals 8 votes, 245 views
Who has more controlling Power over Environmental concerns...???
 
1428 referals 48 arguments, 1952 views
We are living in a fast world. People fall in love fast and get separated faster. Why can’t...
 
1550 referals 30 arguments, 429 views
more...  
Recent Knowledge (55)
HI The most stressful part of job interview is to get stuck in those questions which are generic...
 
0 referals 6 comments, 323 views
Many advertisements come and go.. Few make an impression on our mind.. Impression might be good...
1677 referals 20 comments, 643 views
Married men, Enjoy this !!  Unmarried men, Learn from this !! Married/unmarried Women, It is...
 
152 referals 22 comments, 499 views
more...  
More From Author
Anyone statement which cause some uncomfort to common man or mass of the people, nothing wrong in saying Sorry. She is good atleast said sorry. Raj Thakre, Rahul Gandhi, Digvijay Singh and many other politicians never say sorry for their mistakes.
Thanks for sharing the article. Good one
@Munshi: Please don't blame RSS for everything. The sounth India treats all north Indians as aliens. Tamilnadu people know Hindi language but feel shame to speak. They treat any others as outsiders... This all haterated are growing for the benifits of...
more...