Beruflich Dokumente
Kultur Dokumente
General concepts
In this article, I want to tell you how to create and use server side cursors and how you can
optimize a cursor performance.
The server side cursors were first added in SQL Server 6.0 release and now supported in all
editions of SQL Server 7.0 and SQL Server 2000.
Before using cursor, you first must declare the cursor. Once a cursor has been declared, you
can open it and fetch from it. You can fetch row by row and make multiple operations on the
currently active row in the cursor. When you have finished working with a cursor, you
should close cursor and deallocate it to release SQL Server resources.
Declaring a Cursor
Before using cursor, you first must declare the cursor, i.e. define its scrolling behavior and
the query used to build the result set on which the cursor operates. To declare cursor, you
can use a syntax based on the SQL-92 standard and a syntax using a set of Transact-SQL
extensions.
SQL-92 Syntax
cursor_name - the name of the server side cursor, must contain from 1 to 128 characters.
INSENSITIVE - specifies that cursor will use a temporary copy of the data instead of base
tables. This cursor does not allow modifications and modifications made to base tables are
not reflected in the data returned by fetches made to this cursor.
SCROLL - specifies that cursor can fetch data in all directions, not only sequentially until
the end of the result set. If this argument is not specified, FETCH NEXT is the only fetch
option supported.
UPDATE [OF column_name [,...n]] - specifies that all cursor's columns can be updated
(if OF column_name [,...n] is not specified), or only the columns listed in the OF
column_name [,...n] list allow modifications.
cursor_name - the name of the server side cursor, must contain from 1 to 128 characters.
LOCAL - specifies that cursor can be available only in the batch, stored procedure, or
trigger in which the cursor was created. The LOCAL cursor will be implicitly deallocated
when the batch, stored procedure, or trigger terminates.
GLOBAL - specifies that cursor is global to the connection. The GLOBAL cursor will be
implicitly deallocated at disconnect.
FORWARD_ONLY - specifies that cursor can only fetch data sequentially from the first to
the last row. FETCH NEXT is the only fetch option supported.
STATIC - specifies that cursor will use a temporary copy of the data instead of base tables.
This cursor does not allow modifications and modifications made to base tables are not
reflected in the data returned by fetches made to this cursor.
KEYSET - specifies that cursor uses the set of keys that uniquely identify the cursor's rows
(keyset), so that the membership and order of rows in the cursor are fixed when the cursor
is opened. SQL Server uses a table in tempdb to store keyset. The KEYSET cursor allows
updates nonkey values from being made through this cursor, but inserts made by other
users are not visible. Updates nonkey values made by other users are visible as the owner
scrolls around the cursor, but updates key values made by other users are not visible. If a
row is deleted, an attempt to fetch the row returns an @@FETCH_STATUS of -2.
DYNAMIC - specifies that cursor reflects all data changes made to the base tables as you
scroll around the cursor. FETCH ABSOLUTE option is not supported with DYNAMIC cursor.
SCROLL_LOCKS - specifies that cursor will lock the rows as they are read into the cursor to
ensure that positioned updates or deletes made through the cursor will be succeed.
OPTIMISTIC - specifies that cursor does not lock rows as they are read into the cursor. So,
the positioned updates or deletes made through the cursor will not succeed if the row has
been updated outside the cursor since this row was read into the cursor.
TYPE_WARNING - specifies that if the cursor will be implicitly converted from the
requested type to another, a warning message will be sent to the client.
UPDATE [OF column_name [,...n]] - specifies that all cursor's columns can be updated
(if OF column_name [,...n] is not specified), or only the columns listed in the OF
column_name [,...n] list allow modifications.
(L) (G) (FO) (S) (K) (D) (FF) (RO) (SL) (O) (TW) (U)
LOCAL (L) No Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes
GLOBAL (G) No Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes
FORWARD_ONLY (FO) Yes Yes Yes Yes Yes No Yes Yes Yes Yes Yes
STATIC (S) Yes Yes Yes No No No Yes No Yes Yes No
KEYSET (K) Yes Yes Yes No No No Yes Yes Yes Yes Yes
DYNAMIC (D) Yes Yes Yes No No No Yes Yes Yes Yes Yes
FAST_FORWARD (FF) Yes Yes No No No No Yes No No Yes No
READ_ONLY (RO) Yes Yes Yes Yes Yes Yes Yes No No Yes No
SCROLL_LOCKS (SL) Yes Yes Yes No Yes Yes No No No Yes Yes
OPTIMISTIC (O) Yes Yes Yes Yes Yes Yes No No No Yes Yes
TYPE_WARNING (TW) Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes
UPDATE (U) Yes Yes Yes No Yes Yes No No Yes Yes Yes
Opening a Cursor
Once a cursor has been declared, you must open it to fetch data from it. To open a cursor,
you can use the following syntax:
GLOBAL - if this argument was not specified and both a global and a local cursor exist with
the same name, the local cursor will be opened; otherwise, the global cursor will be opened.
cursor_name - the name of the server side cursor, must contain from 1 to 128 characters.
cursor_variable_name - the name of a cursor variable that references a cursor.
After a cursor is opening, you can determine the number of rows that were found by the
cursor. To get this number, you can use @@CURSOR_ROWS scalar function.
Fetching a Cursor
Once a cursor has been opened, you can fetch from it row by row and make multiple
operations on the currently active row in the cursor. To fetch from a cursor, you can use the
following syntax:
FETCH
[ [ NEXT | PRIOR | FIRST | LAST
| ABSOLUTE {n | @nvar}
| RELATIVE {n | @nvar}
]
FROM
]
{ { [GLOBAL] cursor_name } | @cursor_variable_name}
[INTO @variable_name[,...n] ]
where
NEXT - the default cursor fetch option. FETCH NEXT returns the next row after the current
row.
ABSOLUTE {n | @nvar} - returns the nth row in the cursor. If a positive number was
specified, the rows are counted from the top of the data set; if 0 was specified, no rows are
returned; if a negative number was specified, the number of rows will be counted from the
bottom of the data set.
RELATIVE {n | @nvar} - returns the nth row in the cursor relative to the current row. If a
positive number was specified, returns the nth row beyond the current row; if a negative
number was specified, returns the nth row prior the current row; if 0 was specified, returns
the current row.
GLOBAL - if this argument was not specified and both a global and a local cursor exist with
the same name, the local cursor will be fetched; otherwise, the global cursor will be fetched.
cursor_name - the name of the server side cursor, must contain from 1 to 128 characters.
Closing a Cursor
When you have finished working with a cursor, you can close it to release any resources and
locks that SQL Server may have used while the cursor was open.
To close a cursor, you can use the following syntax:
GLOBAL - if this argument was not specified and both a global and a local cursor exist with
the same name, the local cursor will be closed; otherwise, the global cursor will be closed.
cursor_name - the name of the server side cursor, must contain from 1 to 128 characters.
Note. If you have closed a cursor, but have not deallocated it, you can open it again when
needed.
Deallocating a Cursor
When you have finished working with a cursor and want to completely release SQL Server
resources that were used by a cursor, you can deallocate a cursor.
To deallocate a cursor, you can use the following syntax:
GLOBAL - if this argument was not specified and both a global and a local cursor exist with
the same name, the local cursor will be deallocated; otherwise, the global cursor will be
deallocated.
cursor_name - the name of the server side cursor, must contain from 1 to 128 characters.
Note. Deallocating a cursor completely removes all cursor references. So, after a cursor is
deallocated, it no longer can be opened.