Está en la página 1de 7

Manejo de Cursores en SQL Server

CURSORES DE TRANSACT-SQL
Una de las caractersticas que definen las bases
de datos relacionales es que las operaciones se
ejecutan sobre un conjunto de filas. Un conjunto
puede estar vaco, o contener una sola fila, pero
aun as se considera un conjunto. Esto es
necesario y til en operaciones relacionales, pero
en algunas ocasiones puede no ser conveniente
para las aplicaciones.
Por ejemplo dado que no hay un modo de apuntar
a una fila especfica de un conjunto, mostrar cada
vez una fila al usuario puede ser difcil. E incluso
aunque las extensiones al SQL estndar
proporcionadas por Transact-SQL hace al SQL
mas programable, aun existen operaciones
difciles, caras o simplemente imposibles de
realizar sobre un conjunto base.
Para manejar estas situaciones, SQL admite los
cursores. Un cursor es un objeto que apunta a
una fila especfica dentro de un conjunto.
Dependiendo de la naturaleza del cursor que cree,
puede mover el cursor por el conjunto y modificar
o borrar datos.
Los cursores Tansact-SQL se crean utilizando el
comando DECLARE CURSOR. Tanto el objeto
cursor como el conjunto de filas al que apunta
existen en el servidor. Este se denomina un
cursor de lado de servidor. Cuando utilice un
cursor de este tipo desde una aplicacin
conectada a SQL Server por una red, cada
operacin sobre el cursor requiere de un viaje a
travs de la red.
El conjunto de filas a las que apunta el cursor se
define por un comando SELECT. Existen algunas
restricciones sobre la sentencia SELECT cuando se
crea un cursor Transact-SQL:
No puede devolver mltiples conjunto de
resultados.
No puede contener la clusula INTO para crear
una nueva tabla.
No puede contener clusulas COMPUTE o
COMPUTE BY utilizadas para agregar resultados.
Caractersticas de los Cursores
Transact-SQL admite varios tipos diferentes de
cursores. Ordenarlos por las caractersticas de
cada tipo puede ser confuso, pero resulta mas
fcil si piensa en cada tipo en trminos de tres
caractersticas mas o menos independientes de
los cursores: su habilidad para reflejar los
cambios de los datos subyacentes, su habilidad
para moverse a travs del conjunto de filas, y su
habilidad para modificar el conjunto de filas.
Reflejar cambios
Cuando un cursor refleja los cambios realizados
sobre los datos subyacentes nos referimos a ello

Adm. Base de Datos II

como sensibilidad. Por ejemplo: suponga que crea


un cursor para la sentencia:
SELECT
*
FROM
CUSTOMERS
LEFT(COMPANYNAME , 1) = ' A'

WHERE

La base de datos Northwind devolver 4 filas, si


durante el tiempo en que est utilizando el cursor,
alguien altera un valor para el campo CITY o
agrega un nuevo COMPANYNAME que empieza
con A, Que sucede con el conjunto de filas a las
que apunta su cursor?
Se pueden determinar 2 tipos de sensibilidad por
separado cuando creas cursores: los cambios de
filas incluidos en el conjunto (la pertenencia al
conjunto) y los cambios de los valores de las filas
subyacentes.
Movimiento
La segunda caracterstica del cursor es si puede o
no utilizar para moverse hacia adelante y hacia
atrs, o solo hacia adelante. Aqu se aplica el
dilema proverbial de la programacin de la
velocidad contra la flexibilidad. Los cursores solo
hacia adelante (forward-only) son bastante mas
rpidos, pero obviamente menos flexibles.
Modificacin
La caracterstica final utilizada para clasificar
cursores es si las filas se pueden o no modificar a
travs del cursor. De nuevo, los cursores de solo
lectura son generalmente ms eficientes pero
menos flexibles.
Tipos de Cursor
Transact-SQL admite 4 tipos diferentes de
cursores: static, keyset, dynamic y firehose. Cada
tipo de cursor almacena diferentes datos sobre las
filas a las que apunta, y cada uno admite
diferentes combinaciones de las caractersticas de
cursor descritas en la seccin anterior.
Static
Un cursor esttico toma una instantnea de los
datos especificados por su sentencia SELECT y los
almacena en la base de datos tempdb. No existe
sensibilidad hacia los cambios de pertenencia o
valores de los datos, y dado que cualquier
modificacin nicamente se reflejara en la copia,
son siempre de solo lectura. Los cursores
estticos pueden, en cualquier caso, declararse
como de solo hacia adelante (forward-only) o con
movimiento en ambos sentidos.
Keyset
Un cursor de tipo keyset(conjunto de claves)
copia en tempdb solo las columnas necesarias
para identificar de forma nica cada fila. A la hora
de declarar un cursor keyset, cada tabla
involucrada en la sentencia SELECT de la

Manejo de Cursores en SQL Server


definicin debe tener un ndice nico que defina el
conjunto de claves a copiar.

FOR sentencia_seleccion
[FOR UPDATE [OF nombre_columnas]]

Los cursores keyset pueden ser modificables o de


solo lectura, y desplazables en ambos sentidos o
solo hacia delante.

Observe que todos los parmetros que definen las


caractersticas del cursor, visibilidad, tipo, etc,
son opcionales. Los valores por defecto son
complejos, con parmetros especificados y no
especificados que interactan con los registros o
vistas subyacentes y con las opciones de la base
de datos.

La propiedad de un cursor se fija cuando se


declara el cursor. Si se aade una fila que podra
satisfacer el criterio de seleccin mientras que el
cursor esta abierto, no se aadir al conjunto. En
el ejemplo anterior, donce el criterio de seleccin
era LEFT(COMPANYNAME , 1)= A, una nueva fila
con el valor Antunez en la columna companyname
no se aadirn a las filas afectadas por el cursor.
Dynamic
Conceptualmente un cursor dinmico se comporta
como si se ejecutara la sentencia SELECT cada
vez que se hace referencia a una fila. Los
cursores dinmicos reflejan los cambios tanto de
pertenencia como de los valores de los datos
subyacentes, tanto si estos cambios se han
realizado a travs del cursor o por otros usuarios.
Existe una restriccin en los cursores dinmicos:
la sentencia SELECT utilizada para definirlos
puede contener una clusula ORDER BY solo si
hay un ndice que contiene las columnas utilizadas
en la clusula ORDER BY. Si declara un cursor
dinmico con una clusula ORDER BY no aadida
a un ndice, SQL Server convertir el cursor a un
cursor de tipo keyset.
Firehose
SQL Server admite una forma especialmente
optimizada de un cursor de solo lectura, solo
hacia delante. Este tipo de cursor se declara
utilizando FAST_FORWARD, pero es mas conocido
como cursor firehose.
Los cursores firehose son muy eficientes, pero
hay 2 restricciones importantes al utilizarlos.
Primero si la sentencia SELECT utilizada para
definir el cursor hace referencia a columna
text,ntext, o image y contiene una clusula top,
SQL Server lo convierte a un cursor de tipo
keyset.
Segundo, si la sentencia SQLECT que utiliza para
definir el cursor combina tablas que tiene
desencadenadores con tablas que no tienen
desencadenadores, el cursor se convierte en un
cursor esttico.
Utilizar Cursores
Sintaxis:
DECLARE nombre_cursor CURSOR
[visibilidad]
[movimiento]
[tipo]
[bloqueo]
[TYPE_WARNING]

Adm. Base de Datos II

La visibilidad de un cursor se define con la


palabra clave LOCAL o GLOBAL. Tiene el mismo
efecto que utilizar @tabla_local o @@tabla_global
para declarar tablas temporales.
El parmetro movimiento acepta las palabras
claves FORWARD_ONLY y SCROLL, movimiento
solo hacia delante o en ambos sentidos
respectivamente.
El parmetro tipo determina el tipo de cursor a
crear. Las palabras claves son STATIC, KEYSET,
DYNAMIC y FAST_FORWARD. El parmetro de
tipo FAST_FORWARD y el parmetro de
movimiento FORWARD_ONLY son mutuamente
excluyentes.
El parmetro bloqueo determina si puede
modificarse una fila a travs del cursor, y si otros
usuarios pueden modificarlas o no. Si utiliza la
palabra reservada READ_ONLY, no se podrn
realizar cambios a los datos subyacentes a travs
del cursor. Aun es posible que otros usuarios
modifiquen los datos utilizando una sentencia
UPDATE estndar. Si especifica SCROLL_LOCKS
como parmetro de bloqueo, las modificaciones
se pueden realizar nicamente a travs del
cursor. Cualquier otra sentencia UPDATE fallara.
La ultima opcin de bloqueo OPTIMISTIC, le
permite modificar las filas tanto a travs del
cursor como desde fuera de el. Esta es la opcin
ms flexible.
La sentencia_seleccion especificada en la clusula
FOR es obligatoria. Especifica las filas a incluir en
el conjunto de datos del cursor.
La clusula FOR UPDATE es opcional. Por defecto,
los cursores son modificables. Puede utilizar OF
nombre_columnas para identificar las columnas
especificas que admiten cambios. Si omite OF
nombres_columnas, todas las columnas de la
sentencia SELECT sern modificables.
Variables Cursor
Transact-SQL le permite declarar variables de tipo
CURSOR. En este caso, la sintaxis DECLARE no
crea el cursor; debe explcitamente establecer
(SET) la variable al cursor:
DECLARE miCursor CURSOR
LOCAL
FAST_FORWARD
FOR SELECT * FROM Customers

Manejo de Cursores en SQL Server


DECLARE @varCursor CURSOR
SET @varCursor = miCursor
GO
Abrir un Cursor
Al declarar un cursor crea el objeto cursor, pero
no crea el conjunto de registros que manipulara el
cursor (el conjunto de cursor). El conjunto de
cursor no se crea hasta que se abre el cursor.
OPEN [GLOBAL] cursor_o_variable
Cerrar un Cursor
Una vez ha terminado de utilizar un cursor,
deber cerrarlo. La sentencia CLOSE libera los
recursos utilizados en mantener el conjunto de
cursor, y tambin libera cualquier bloqueo sobre
las filas si ha utilizado SCROLL_LOCKS de la
sentencia DECLARE.
CLOSE [GLOBAL] cursor_o_variable
Liberar un Cursor
La ltima sentencia en la secuencia de creacin
de un cursor es DEALLOCATE.
DEALLOCATE [GLOBAL] cursor_o_variable
Manipular filas mediante un cursor
Los cursores no serian interesantes si no pudiera
hacer algo con ellos. Transact-SQL soporta 3
comandos diferentes para trabajar con cursores:
FETCH, UPDATE y DELETE.
El comando FETCH recupera una fila especfica del
conjunto cursor. En su forma ms simple, el
comando FETCH tiene la sintaxis:
FETCH cursor_o_variable
Este formato obtiene la fila en la cual esta
posicionando el cursor (la fila actual).
Ejemplo:
USE NorthWind
GO
-- Crear el cursor
DECLARE cursorSimple CURSOR
LOCAL
FOR
SELECT
CompanyName
Customers
-- Crea el conjunto de cursor
OPEN cursorSimple
-- Recupera una fila (la primera)
FETCH cursorSimple
-- Cierra el conjunto de cursor
CLOSE cursorSimple
-- Libera el cursor
DEALLOCATE cursorSimple
GO

Adm. Base de Datos II

FROM

En lugar de obtener una fila directamente, el


comando FETCH le permite almacenar los valores
obtenidos de las columnas en variables. Para
almacenar los resultados del FETCH en una
variable, utilice la siguiente sintaxis:
FETCH cursor_o_variablecursor
INTO lista_variables
La lista_variables es una lista separada por comas
de identificadores de variables. Debe declarar las
variables antes de ejecutar el comando FETCH. La
lista_variables debe incluir una variable por cada
columna de la sentencia SELECT que define el
cursor, y los tipos de datos de las variables deben
ser igual o compatibles con los tipos de datos de
la columna.
Ejemplo:
USE NorthWind
GO
-- Crea el cursor y algunas variables
-- Clientes que no Tengan Ordenes
DECLARE cursorSimple CURSOR
LOCAL FOR SELECT CustomerId, CompanyName
FROM Customers
WHERE CustomerId NOT IN
(SELECT DISTINCT CustomerId FROM ORDERS)
DECLARE @elCodigo char(5),
@elNombre char(50)
-- Crea el conjunto de cursor
OPEN cursorSimple
-- Recupera los valores en variables
FETCH cursorSimple
INTO @elCodigo, @elNombre
-- Muestra los resultados
PRINT RTRIM(@elCodigo) + ' es el Codigo'
PRINT RTRIM(@elNombre) + ' es el Nombre del
Cliente'
-- Cierra el conjunto de resultados
CLOSE cursorSimple
-- Libera el cursor
DEALLOCATE cursorSimple
GO

Manejo de Cursores en SQL Server

Si
su
cursor
es
FORWARD_ONLY
o
FAST_FORWARD, la unica palabra clave de
posicionamiento que puede utilizar es NEXT. En
realidad, si su cursor es de alguno de los tipos
anteriores, no es necesario NEXT. SQL Server
asume que todo FETCH es un FETCH NEXT
En el primer ejemplo de cursores si lo
modificamos para que tenga esta apariencia, nos
mostrara todas las filas:
USE NorthWind
GO
-- Crear el cursor
DECLARE cursorSimple CURSOR
LOCAL
FOR SELECT CompanyName FROM Customers
-- Crea el conjunto de cursor
OPEN cursorSimple
-- Recupera una fila (la primera)
FETCH cursorSimple
WHILE @@FETCH_STATUS=0
FETCH cursorSimple
-- Cierra el conjunto de cursor
CLOSE cursorSimple
-- Libera el cursor
DEALLOCATE cursorSimple
GO

Utilizando
FIREHOSE

FETCH

NEXT

con

un

cursor

USE NorthWind
GO
DECLARE cursorSimple CURSOR
LOCAL
FAST_FORWARD
FOR
SELECT CompanyName FROM Customers
DECLARE @elNombre char(20)
DECLARE @contador int
OPEN cursorSimple
-- Muestra 6 filas
SET @contador = 1
WHILE @contador <= 6
BEGIN
FETCH cursorSimple INTO @elNombre
PRINT RTRIM(@elNombre) +
' --> es el nombre ' + LTRIM(STR(@contador))
SET @contador = @contador + 1
END
CLOSE cursorSimple
DEALLOCATE cursorSimple
GO

Adm. Base de Datos II

Manejo de Cursores en SQL Server


-- Creando una tabla conteniendo todos los
-- registros de la tabla Customers
SELECT * INTO TblClientes
FROM Customers
GO

Modificar y Eliminar filas de un cursor


Si su cursor es modificable, cambiar los valores
subyacentes en el conjunto de cursor es bastante
simple. Existe una forma especial de la clusula
WHERE que admite la modificacin a travs de un
cursor:
UPDATE tabla_o_vista
SET lista_modificacin
WHERE CURRENT OF cursor_o_variablecursor
A esto se le denomina una modificacin
posicional. Transact-SQL tambin admite una
eliminacin posicional de la forma:
DELETE tabla_o_vista
WHERE CURRENT OF cursor_o_variablecursor
Ejemplo:
--DROP TABLE TmpPrueba
-- Creando una tabla para insertar los
-- clientes actualizados en el campo
-- Region(NULL)
CREATE TABLE TmpPrueba
(codigo CHAR(5),
nombre VARCHAR(40))
GO

USE NorthWind
GO
DECLARE cursorSimple CURSOR
LOCAL
FOR
SELECT CustomerId, CompanyName, Region
FROM TblClientes
DECLARE @codigo char(5),
@nombre varchar(40), @region varchar(15)
OPEN cursorSimple
-- Lee la primera fila
FETCH cursorSimple
INTO @codigo,@nombre,@region
-- Si no hay error
WHILE (@@FETCH_STATUS=0)
BEGIN
-- si el campo @region es NULO
IF (@region IS NULL)
BEGIN
-- Cambia el campo Region(NULL)
UPDATE TblClientes
SET Region = 'Ya no es NULL'
WHERE CURRENT OF cursorSimple
-- Insertamos una nueva Fila en la tabla
-- TmpPrueba con los clientes
-- actualizados
INSERT TmpPrueba
VALUES(@codigo,@nombre)
END
-- Leemos la siguiente fila
FETCH cursorSimple
INTO @codigo,@nombre,@region
END
-- Cerramos y Liberamos el cursor
CLOSE cursorSimple
DEALLOCATE cursorSimple
GO
-- Verificando las Actualizaciones
-- sobre el campo region
SELECT * FROM TblClientes
WHERE region='Ya no es NULL'
GO
-- Verificando en la nueva tabla todos los
-- clientes que han sido actualizados en el
-- campo region(NULL)
SELECT * FROM TmpPrueba
GO

-- Saber cuantas filas son nulas en el campo


-- Region de la tabla Customers
SELECT * FROM Customers
WHERE Region IS NULL
GO
--DROP TABLE TblClientes
--GO

Adm. Base de Datos II

Manejo de Cursores en SQL Server


la variable cursor
informacin.

para

la

que

se

solicita

Valor_Retorno

Significado

Si la funcin se llamo con un


cursor dinmico, el conjunto de
cursor tiene cero, una o ms
filas. Si la funcin se llamo con
otro tipo de cursor, tiene al
menos una fila.
El conjunto de cursor esta
vaco.
El cursor esta cerrado
Devuelto solo por variables de
cursor.
O
bien
el cursor
asignado
a
la
variable
especificada esta cerrado o bien
no se ha asignado aun ningn
cursor a la variable.
El cursor especificado o la
variable cursor no existen.

0
-1
-2

-3
Monitorizar los cursores Transact-SQL
Transact-SQL proporciona dos variables globales
y una funcin que le ayudara a comprender que
esta
sucediendo
con
sus
cursores
@@CURSOR_ROWS devuelve el numero de filas
del ultimo cursor abierto en la conexin.
Valor_Retorno

Significado

-m

El cursor aun no se ha
terminado de poblar; existen
actualmente m filas en el
conjunto de cursor
El cursor es dinmico y el
numero de filas puede cambiar
O no se ha abierto ningn
cursor, o se ha cerrado o
liberado
el
ultimo
cursor
abierto, o el cursor no contiene
ninguna fila.
El numero de filas es n

-1
0

@@FETCH_STATUS obtiene la informacin sobre


el ltimo comando FETCH ejecutado.
Valor_Retorno

Significado

El comando FETCH se ejecut


correctamente.

-1

El comando FETCH Fallo.

-2

La fila leda desapareci

Por ultimo Transact-SQL proporciona la funcin


CURSOR_STATUS, que tiene la siguiente sintaxis:
CURSOR_STATUS( tipo, cursor_o_variable)
El valor de tipo es local,global, o variable, y
cursor_o_variable es el identificador del cursor o

Adm. Base de Datos II

Ejemplo:
USE NorthWind
GO
DECLARE cursorsimple CURSOR
LOCAL STATIC
FOR
SELECT CompanyName FROM Customers
WHERE Region IS NOT NULL
OPEN cursorsimple
-- Muestar el Nro de filas
SELECT @@CURSOR_ROWS
AS 'FilasCursor(@@CURSOR_ROWS)'
-- Obtiene la primera fila
FETCH cursorsimple
-- Muestra los resultados de la ltima lectura
SELECT @@FETCH_STATUS
AS 'EstadoFETCH(@@FETCH_STATUS)'
-- Comprueba el estado del cursor
SELECT CURSOR_STATUS('local','cursorsimple')
AS 'EstadoCursor(CURSOR_STATUS)'
-- Obtiene la ltima fila
FETCH LAST FROM cursorsimple
-- Cerramos el Cursor
CLOSE cursorsimple
-- Cursor o variable Cursor Cerradas
SELECT CURSOR_STATUS('local','cursorsimple')
AS 'EstadoCursor(CURSOR_STATUS)'
-- Liberamos el Cursor
DEALLOCATE cursorsimple
-- Cursor o variable Cursor No Existen
SELECT CURSOR_STATUS('local','cursorsimple')
AS 'EstadoCursor(CURSOR_STATUS)'
GO

Manejo de Cursores en SQL Server

Adm. Base de Datos II

También podría gustarte