Skip to content

Cursores

Un cursor es un objeto que permite recorrer de manera secuencial un conjunto de datos, fila por fila. A diferencia de las consultas tradicionales que operan sobre conjuntos de datos completos, un cursor permite procesar cada registro de forma individual dentro de un bucle, lo que es útil para tareas que no se pueden realizar con operaciones basadas en conjuntos.

Para trabajar con cursores, se deben seguir estos pasos:

  1. Declarar el cursor (DELCARE)
  2. Abrir el cursor (OPEN)
  3. Leer los datos de la primera fila (FETCH...INTO)
  4. Recorrer las filas con un bucle (WHILE @@FETCH_STATUS = 0)
  5. Cerrar el cursor (CLOSE)
  6. Liberar los recursos (DEALLOCATE)

-- Declaración del cursor
DECLARE <nombre_cursor> CURSOR FOR
<sentencia_sql>
-- Apertura del cursor
OPEN <nombre_cursor>
-- Lectura de la primera fila del cursor
FETCH <nombre_cursor> INTO <lista_variables>
WHILE (@@FETCH_STATUS = 0) -- Recorrido de filas mientras la lectura sea exitosa
BEGIN
-- Procesamiento de la fila actual
-- ...
-- Lectura de la siguiente fila del cursor
FETCH <nombre_cursor> INTO <lista_variables>
END
-- Cierre del cursor
CLOSE <nombre_cursor>
-- Liberación de los recursos del cursor
DEALLOCATE <nombre_cursor>

Este ejemplo muestra cómo declarar, abrir y recorrer un cursor para imprimir los detalles de los artículos.

DECLARE
@ID INT,
@nom VARCHAR(255),
@descripcion VARCHAR(255),
@precio VARCHAR(255);
DECLARE cArticulos CURSOR FOR
SELECT ID, nom, precio, descripcion
FROM Articulos;
OPEN cArticulos;
FETCH NEXT FROM cArticulos INTO @ID, @nom, @descripcion, @precio;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @nom + ', ' + @descripcion + ', ' + @precio;
FETCH NEXT FROM cArticulos INTO @ID, @nom, @descripcion, @precio;
END;
CLOSE cArticulos;
DEALLOCATE cArticulos;

La función @@FETCH_STATUS indica el estado de la última instrucción FETCH:

ValorDescripción
0La instrucción FETCH se ejecutó correctamente.
-1La instrucción FETCH falló o la fila estaba fuera del conjunto de resultados.
-2La fila recuperada no existe.

Puedes modificar el comportamiento de un cursor con una serie de parámetros opcionales. La sintaxis completa para la declaración es:

DECLARE <nombre_cursor> CURSOR
[ LOCAL | GLOBAL ]
[ FORWARD_ONLY | SCROLL ]
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
[ TYPE_WARNING ]
FOR <sentencia_sql>
  • LOCAL: El ámbito del cursor es local a la función, procedimiento almacenado o lote en el que fue creado. No es visible fuera de ese ámbito.
  • GLOBAL: El cursor es visible para cualquier procedimiento, lote o trigger que se ejecute dentro de la misma conexión.

Nota:

Si no se especifica GLOBAL ni LOCAL, el valor predeterminado se controla mediante la opción de base de datos default to local cursor.


  • FORWARD_ONLY: El cursor solo puede avanzar de la primera a la última fila. Solo permite la lectura en una dirección.
  • SCROLL: Habilita todas las opciones de recuperación (FIRST, LAST, PRIOR, NEXT, RELATIVE, ABSOLUTE), lo que permite la lectura en cualquier dirección.
-- Ejemplo de cursor SCROLL
DECLARE
@ID INT,
@nom VARCHAR(255),
@descripcion VARCHAR(255),
@precio VARCHAR(255);
DECLARE cArticulos CURSOR SCROLL FOR
SELECT ID, nom, precio, descripcion
FROM Articulos;
OPEN cArticulos;
-- Lectura de la primera fila
FETCH NEXT FROM cArticulos INTO @ID, @nom, @descripcion, @precio;
PRINT 'Primera fila: ' + @nom;
-- Lectura de la última fila
FETCH LAST FROM cArticulos INTO @ID, @nom, @descripcion, @precio;
PRINT 'Última fila: ' + @nom;
CLOSE cArticulos;
DEALLOCATE cArticulos;

Tipos de Cursores: STATIC, KEYSET, DYNAMIC y FAST_FORWARD

Section titled “Tipos de Cursores: STATIC, KEYSET, DYNAMIC y FAST_FORWARD”
  • STATIC: Crea una copia de los datos en tempdb al abrir el cursor. Los cambios en las tablas base no se reflejan en el cursor. No permite modificaciones.
  • KEYSET: El conjunto de filas del cursor se fija cuando se abre. Los cambios en los valores de las filas son visibles, pero las inserciones o eliminaciones de filas no.
  • DYNAMIC: El cursor refleja todos los cambios realizados en los datos subyacentes. El conjunto de resultados, el orden y los valores de las filas pueden cambiar con cada operación FETCH.
  • FAST_FORWARD: Un cursor FORWARD_ONLY y READ_ONLY con optimizaciones de rendimiento. No puede usarse con SCROLL o FOR_UPDATE.

Concurrencia: READ_ONLY, SCROLL_LOCKS y OPTIMISTIC

Section titled “Concurrencia: READ_ONLY, SCROLL_LOCKS y OPTIMISTIC”
  • READ_ONLY: Impide que se realicen actualizaciones a través del cursor. Es la opción predeterminada para cursores que no permiten actualizaciones.
  • SCROLL_LOCKS: Garantiza que las actualizaciones y eliminaciones realizadas a través del cursor sean exitosas. Bloquea las filas al leerlas para evitar que otros usuarios las modifiquen. No se puede usar con FAST_FORWARD o STATIC.
  • OPTIMISTIC: Permite actualizaciones, pero verifica si la fila ha sido modificada por otro usuario desde que se leyó. Si se detecta un cambio, la operación fallará. Utiliza marcas de tiempo o sumas de comprobación. No se puede usar con FAST_FORWARD.