Click here to Skip to main content
Click here to Skip to main content

Tagged as

Cursors Vs. Sets

, 19 Nov 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
A brief discussion of when to use cursors and when to use sets.

Introduction

Cursors, they say, do not use them. They are absolutely right... and wrong at the same time. Smile | :)

If Cursors are that bad, then why are they not removed from SQL??

Background

Cursors are probably slow in performance with respect to normal code (Sets), therefore, we avoid using them. But at the same time, they are unavoidable, and are preferred to be used in cases where there is a need to prepare dynamic SQL or complex logics row by row basis.

This tip is primarily to focus on determining a boundary between the two (Cursors and Sets).

Explained

Cursor

If developers have worked in VB (Visual Basic) precisely in recordsets, it works in a similar fashion to that of a cursor.

The cursor iterates through every single row for processing, each time when it fetches a row, it performs a network round trip. Since it is round tripped, the network bandwidth would go for a toss and repeatedly doing this can have a direct impact of the operation used in cursor.

Following is a simple code on how cursors are used in SQL procedures:

  1. Declare a cursor that defines a result set.
  2. Open the cursor to establish the result set.
  3. Fetch the data into local variables as needed from the cursor "one row at a time".
  4. Close the cursor when done.

Here is the sample code of a cursor:

DECLARE cust_cursor CURSOR
    FOR SELECT * FROM Cutomers
OPEN cust_cursor
FETCH NEXT FROM cust_cursor;
CLOSE cust_cursor 

Sets

SQL works on sets, i.e., with set of records. The fundamental approach of SQL is to differentiate a pool of data logically. Therefore, Sets can replace the cursor to maximum level.These are normal SQL queries.

The below example shows the difference between them.

Example

Problem: Update all the records in Customer table with respective pincode using table Pincode_Details.

Solution using the Cursor

Here is what the code says:

  1. Fetch the records (Telephone numbers) having pincode null, from table Customer.
  2. Iterate every fetched record, and break the preceding 4 digits of telephone number.
  3. Find the respective pincode from Pincode_details using the number fetched in step 2.
  4. For every record, check if the variable @pincode is not a null and update the pincode into Customer table.
DECLARE @telnumber char(8)
DECLARE cust_cursor CURSOR FOR					--
   SELECT TelNumber FROM Customer WHERE PinCode IS NULL		--
OPEN cust_cursor						--
FETCH NEXT FROM cust_cursor  INTO @telnumber			-- (1)
WHILE @@FETCH_STATUS = 0 BEGIN
   Declare @pincode char(6)
   DECLARE @centerid char(4)
   SELECT @centerid = LEFT(@telnumber, 4)			-- (2)

   SELECT @pincode = PinCode 					--
   FROM PinCode_Details 					--
   WHERE Centerid = @centerid					-- (3)

   IF @pincode IS NOT NULL 					--
   BEGIN							--
       UPDATE Customer SET PinCode = @pinCode			--
       WHERE CURRENT OF cust_cursor 				--
   END								-- (4)
   FETCH NEXT FROM cust_cursor INTO @telnumber
END
CLOSE cust_cursor 
DEALLOCATE cust_cursor

Solution using the Sets

A single update query with join will achieve the same result.

UPDATE Customer 
SET PinCode = PinCode_Details.PinCode 
FROM Customer
JOIN PinCode_Details ON
    LEFT(Customer.PhoneNumber, 4) = PinCode_Details.Centerid
WHERE
    Customer.PinCode IS NULL

Advantage of Sets over Cursor in the Above Example

  1. 'Sets' is recommended as there will be a noticeable improvement in the query results.
  2. Code is easily readable and understandable.
  3. There will be no network round trips.
  4. Query can be optimized with indexing.

Now the Question is, When Can We Use the Cursor?

Sets are only bound to be used where the developer builds the query with a prior knowledge of what user is going to see or use.

  1. Cursors can be used in a situation where the user is given an interface to logically group the data. Then, the developer would have no idea on what kind of grouping will be done by the user.
  2. Or as per the below example, if an event has to be fired to update a table present in all the databases ('ClientProductionOne','ClientProductionTwo','ClientProductionThree'), then approach of cursor will help you.
DECLARE @dbname VARCHAR(50)
DECLARE @databasename VARCHAR(256)
DECLARE @SQL varchar(8000)
 
SET	@SQL = 'UPDATE  @dbname.dbo.tbldailyEventFired
		SET EndTime = CONVERT(datetime,''2014-11-18 23:59:00'',120) 
		WHERE EndTime = (CONVERT(datetime,''2015-11-17 23:59:00'',120))'
 
DECLARE db_cursor CURSOR FOR 
	SELECT name 
	FROM master.dbo.sysdatabases
	WHERE name IN ('ClientProductionOne','ClientProductionTwo','ClientProductionThree')
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @dbname
WHILE	(@@FETCH_STATUS = 0)
BEGIN
	SET	@SQL	= REPLACE(@SQL, '@dbname', @dbname)
	EXEC	(@SQL)
        FETCH NEXT FROM db_cursor INTO  @dbname 
END
CLOSE db_cursor
DEALLOCATE db_cursor
GO

Points of Interest

In this tip, we have tried to help developers determine the approach (on choosing Cursor or Sets), probably a better one and to clearly point out the right choice of using the same.

Thanks to all my distinguished seniors / colleagues of my career, for passing on their views and approaches when using Cursors and Sets.

History

  • 18th November, 2014: First version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sums Mohs Eds
Software Developer (Senior)
India India
No Biography provided

Comments and Discussions

 
BugBug: dynamic SQL problem PinmemberRammer1422321-Nov-14 6:23 
QuestionSome feedback: [modified] PinmemberKP Lee20-Nov-14 23:11 
AnswerRe: Some feedback: PinmemberSums Mohs Eds21-Nov-14 0:13 
GeneralRe: Some feedback: PinmemberKP Lee21-Nov-14 1:28 
SuggestionIf those // are comments.. PinprofessionalAfzaal Ahmad Zeeshan19-Nov-14 8:33 
GeneralRe: If those // are comments.. PinmemberSums Mohs Eds19-Nov-14 20:44 
AnswerRe: If those // are comments.. PinprofessionalAfzaal Ahmad Zeeshan19-Nov-14 22:37 
GeneralRe: If those // are comments.. PinmemberSums Mohs Eds19-Nov-14 23:31 
GeneralMy vote of 5 PinmemberRUs12319-Nov-14 3:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150414.1 | Last Updated 19 Nov 2014
Article Copyright 2014 by Sums Mohs Eds
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid