0% found this document useful (0 votes)
75 views

Cursor

Cursors allow processing data row-by-row and are useful when stored procedures need to be called on each row. However, cursors are very slow compared to set-based operations. The basic syntax involves declaring a cursor, opening it to populate the result set, fetching rows into variables, and closing the cursor. Cursors should only be used when truly necessary to access rows individually.

Uploaded by

Sachin Kumar
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
75 views

Cursor

Cursors allow processing data row-by-row and are useful when stored procedures need to be called on each row. However, cursors are very slow compared to set-based operations. The basic syntax involves declaring a cursor, opening it to populate the result set, fetching rows into variables, and closing the cursor. Cursors should only be used when truly necessary to access rows individually.

Uploaded by

Sachin Kumar
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

We'll talk about the basics of cursors.

These let you move through rows one at a time and perform
processing on each row. (This article has been updated through SQL Server 2005.)

SQL Server is very good at handling sets of data. For example, you can use a single UPDATE
statement to update many rows of data. There are times when you want to loop through a series of
rows a perform processing for each row. In this case you can use a cursor.

Please note that cursors are the SLOWEST way to access data inside SQL Server. The should only be
used when you truly need to access one row at a time. The only reason I can think of for that is to call
a stored procedure on each row.  In theCursor Performance article I discovered that cursors are
over thirty times slower than set based alternatives.

The basic syntax of a cursor is:

DECLARE @AuthorID char(11)

DECLARE c1 CURSOR READ_ONLY


FOR
SELECT au_id
FROM authors

OPEN c1

FETCH NEXT FROM c1


INTO @AuthorID

WHILE @@FETCH_STATUS = 0
BEGIN

PRINT @AuthorID

FETCH NEXT FROM c1


INTO @AuthorID

END

CLOSE c1
DEALLOCATE c1

The DECLARE CURSOR statement defines the SELECT statement that forms the basis of the cursor.
You can do just about anything here that you can do in a SELECT statement. The OPEN statement
statement executes the SELECT statement and populates the result set. The FETCH statement
returns a row from the result set into the variable. You can select multiple columns and return them
into multiple variables. The variable @@FETCH_STATUS is used to determine if there are any more
rows. It will contain 0 as long as there are more rows. We use a WHILE loop to move through each
row of the result set.

The READ_ONLY clause is important in the code sample above.  That dramatically improves the
performance of the cursor.
In this example, I just print the contents of the variable. You can execute any type of statement you
wish here. In a recent script I wrote I used a cursor to move through the rows in a table and call a
stored procedure for each row passing it the primary key. Given that cursors are not very fast and
calling a stored procedure for each row in a table is also very slow, my script was a resource hog.
However, the stored procedure I was calling was written by the software vendor and was a very
easy solution to my problem. In this case, I might have something like this:

EXEC spUpdateAuthor (@AuthorID)

instead of my Print statement. The CLOSE statement releases the row set and the DEALLOCATE
statement releases the resources associated with a cursor.

If you are going to update the rows as you go through them, you can use the UPDATE clause when
you declare a cursor. You'll also have to remove the READ_ONLY clause from above.

DECLARE c1 CURSOR FOR


SELECT au_id, au_lname
FROM authors
FOR UPDATE OF au_lname

You can code your UPDATE statement to update the current row in the cursor like this

UPDATE authors
SET au_lname = UPPER(Smith)
WHERE CURRENT OF c1

That covers the basics of cursors. You can check Books Online for more detailed information.
Cursor (databases)
From Wikipedia, the free encyclopedia

In database packages, a cursor comprises a control structure for the successive traversal (and potential


processing) of records in a result set.

Cursors provide a mechanism by which a database client iterates over the records in a database. Using
cursors, the client can get, put, and delete database records. Database programmers use cursors for
processing individual rows returned by the database system for a query. Cursors address the problem
of impedance mismatch, an issue that occurs in many programming languages [citation needed]. Most procedural
programming languages do not offer any mechanism for manipulating whole result-sets at once. In this
scenario, the application must process rows in a result-set sequentially. Thus one can think of a database
cursor as an iterator over the collection of rows in the result set.

Several SQL statements do not require the use of cursors. That includes the INSERT statement, for example,
as well as most forms of the DELETE and UPDATE statements. Even aSELECT statement may not involve a
cursor if it is used in the variation of SELECT INTO. A SELECT INTO retrieves at most a single row directly

into the application.

Contents
 [hide]

1 Working with cursors

o 1.1 Scrollable cursors

o 1.2 "WITH HOLD"

o 1.3 Positioned update/delete

statements

o 1.4 Cursors in distributed

transactions

o 1.5 Cursors in XQuery

2 Disadvantages of cursors

3 See also

4 References

5 External links

[edit]Working with cursors


This section introduces the ways the SQL:2003 standard defines how to use cursors in applications in
embedded SQL. Not all application bindings for relational database systems adhere to that standard, and some
(such as CLI or JDBC) use a different interface.

A programmer makes a cursor known to the DBMS by using a DECLARE ... CURSOR statement and assigning

the cursor a (compulsory) name:

DECLARE cursor_name CURSOR FOR SELECT ... FROM ...

Before code can access the data, it must open the cursor with the OPEN statement. Directly following a

successful opening, the cursor is positioned before the first row in the result set.

OPEN cursor_name

Programs position cursors on a specific row in the result set with the FETCH statement. A fetch operation

transfers the data of the row into the application.

FETCH cursor_name INTO ...

Once an application has processed all available rows or the fetch operation is to be positioned on a non-
existing row (compare scrollable cursors below), the DBMS returns a SQLSTATE '02000' (usually
accompanied by an SQLCODE +100) to indicate the end of the result set.

The final step involves closing the cursor using the CLOSE statement:

CLOSE cursor_name

After closing a cursor, a program can open it again, which implies that the DBMS re-evaluates the same query
or a different query and builds a new result-set.

[edit]Scrollable cursors
Programmers may declare cursors as scrollable or not scrollable. The scrollability indicates the direction in
which a cursor can move.

With a non-scrollable cursor, also known as forward-only, one can FETCH each row at most once, and the

cursor automatically moves to the immediately following row. A fetch operation after the last row has been
retrieved positions the cursor after the last row and returns SQLSTATE 02000 (SQLCODE +100).
A program may position a scrollable cursor anywhere in the result set using the FETCH SQL statement. The
keyword SCROLL must be specified when declaring the cursor. The default is NO SCROLL, although different

language bindings like JDBC may apply different default.

DECLARE cursor_name sensitivity SCROLL CURSOR FOR SELECT ... FROM ...

The target position for a scrollable cursor can be specified relative to the current cursor position or absolute
from the beginning of the result set.

FETCH [ NEXT | PRIOR | FIRST | LAST ] FROM cursor_name


FETCH ABSOLUTE n FROM cursor_name
FETCH RELATIVE n FROM cursor_name

Scrollable cursors can potentially access the same row in the result set multiple times. Thus, data modifications
(insert, update, delete operations) from other transactions could have an impact on the result set. A cursor can
be SENSITIVE or INSENSITIVE to such data modifications. A sensitive cursor picks up data modifications
impacting the result set of the cursor, and an insensitive cursor does not. Additionally, a cursor may be
ASENSITIVE, in which case the DBMS tries to apply sensitivity as much as possible.

[edit]"WITH HOLD"
Cursors are usually closed automatically at the end of a transaction, i.e when a COMMIT or ROLLBACK (or an
implicit termination of the transaction) occurs. That behavior can be changed if the cursor is declared using the
WITH HOLD clause. (The default is WITHOUT HOLD.) A holdable cursor is kept open over COMMIT and
closed upon ROLLBACK. (Some DBMS deviate from this standard behavior and also keep holdable cursors
open over ROLLBACK.)

DECLARE cursor_name CURSOR WITH HOLD FOR SELECT ... FROM ...

When a COMMIT occurs, a holdable cursor is positioned before the next row. Thus, a positioned UPDATE or
positioned DELETE statement will only succeed after a FETCH operation occurred first in the transaction.

Note that JDBC defines cursors as holdable per default. This is done because JDBC also activates auto-
commit per default. Due to the usual overhead associated with auto-commit and holdable cursors, both
features should be explicitly deactivated at the connection level.

[edit]Positioned update/delete statements


Cursors can not only be used to fetch data from the DBMS into an application but also to identify a row in a
table to be updated or deleted. The SQL:2003 standard defines positioned update and positioned delete SQL
statements for that purpose. Such statements do not use a regular WHERE clause with predicates. Instead, a
cursor identifies the row. The cursor must be opened and already positioned on a row by means
of FETCH statement.

UPDATE table_name
SET ...
WHERE CURRENT OF cursor_name
DELETE
FROM table_name
WHERE CURRENT OF cursor_name

The cursor must operate on an updatable result set in order to successfully execute a positioned update or
delete statement. Otherwise, the DBMS would not know how to apply the data changes to the underlying tables
referred to in the cursor.

[edit]Cursors in distributed transactions


Using cursors in distributed transactions (X/Open XA Environments), which are controlled using a transaction
monitor, is no different than cursors in non-distributed transactions.

One has to pay attention when using holdable cursors, however. Connections can be used by different
applications. Thus, once a transaction has been ended and committed, a subsequent transaction (running in a
different application) could inherit existing holdable cursors. Therefore, an application developer has to be
aware of that situation.

[edit]Cursors in XQuery
The XQuery language allows cursors to be created using the subsequence() function.

The format is:

let $displayed-sequence := subsequence($result, $start, $item-count)

Where $result is the result of the initial XQuery, $start is the item number to start and $item-count is the
number of items to return.

Equivalently this can also be done using a predicate:

let $displayed-sequence := $result[$start to $end]

Where $end is the end sequence.

For complete examples see the XQuery Wikibook.

[edit]Disadvantages of cursors

The following information may vary depending on the specific database system.
Fetching a row from the cursor may result in a network round trip each time. This uses much more network
bandwidth than would ordinarily be needed for the execution of a single SQL statement like DELETE.
Repeated network round trips can severely impact the speed of the operation using the cursor. Some DBMSs
try to reduce this impact by using block fetch. Block fetch implies that multiple rows are sent together from the
server to the client. The client stores a whole block of rows in a local buffer and retrieves the rows from there
until that buffer is exhausted.

Cursors allocate resources on the server, for instance locks, packages, processes, temporary storage, etc. For
example, Microsoft SQL Server implements cursors by creating a temporary table and populating it with the
query's result-set. If a cursor is not properly closed (deallocated), the resources will not be freed until the SQL
session (connection) itself is closed. This wasting of resources on the server can not only lead to performance
degradations but also to failures.

You might also like