A lo largo de este artículo estudiaremos los pasos necesarios para usar un cursor sobre una consulta. Veremos como usar el bucle WHILE para leer completamente la información y finalmente practicaremos con un ejemplo.
Como uso un cursor en SQL Server?
Es sencillo, debemos seguir al pie de la letra las siguientes 5 fases con cada cursor que usemos:
Declaración
Apertura
Lectura
Cierre
Limpieza
Cuando vimos cursores en MySQL solo usábamos las primeras 4 fases debido a que la limpieza de memoria se realizaba automáticamente. En SQL Server nosotros somos los responsables de la limpieza.
1. DECLARACION
La declaración de un cursor en SQL Server se hace con la sentencia DECLARE del estándar SQL-92. Simplemente ponemos un nombre acorde al nuevo cursor y luego indicamos la consulta a la cual apuntará. Veamos:
DECLARE nombre_cursor CURSOR [opciones]
FOR <consulta>;
También podemos indicarle algunas opciones que caractericen el cursor dependiendo de su naturaleza. Entre ellas están:
STATICCrea una copia de la consulta en tempdb(Base de datos para uso temporal de operaciones), para que el cursor apunte justo a esa copia.
KEYSETCrea una tabla con los valores prioritarios de la consulta en la base de datos tempdb. Esto permite crear un JOIN entre la consulta original y dicha tabla para que el cursor itere entre esta relación, por lo que puede ser muy engorroso usar este tipo de cursores.
DYNAMIC
Este tipo de cursor apunta a las filas reales que se obtuvieron en la consulta.FAST_FORWAD
El cursor solo puede ser leído desde el primer elemento hacia el ultimo y será de solo lectura.2. APERTURA
Abrir el cursor significa ejecutar la consulta a la cual hace referencia. Esta operación se realiza con la palabra reservada OPEN, la cual tiene la siguiente sintaxis:
OPEN nombre_cursor;
Si no abres el cursor no se podrá comenzar a leer información con SQL Server.
3. LECTURA
Usaremos el comando FETCH para obtener los datos de las columnas del siguiente registro en la tabla. Es necesario declarar previamente variables que almacenen los valores mientras leemos las filas:
FETCH [orden] nombre_cursorINTO @var1, @var2,...
4. CIERRE
El cierre de un cursor desbloquea el lote de memoria asignado para la consulta. Lo indicamos con la sentencia CLOSE.
CLOSE cursor_nombre;
Hasta este punto el cursor aun existe en la base de datos, por lo que puede volverse a abrir en el futuro.5. LIMPIEZA
En esta fase desasignamos la memoria utilizada por el cursor en la base de datos. Para eliminarlo de la base de datos, usaremos la palabra reservada DEALLOCATE.
DEALLOCATE nombre_cursor;
Como recorro todas las filas de una consulta referenciada por un cursor?
Usaremos el bucle WHILE para realizar esta acción, cuya condición de parada esta dada por el valor que arroje la función del sistema @@FETCH_STATUS. Esta función indica el estado del cursor desde la ultima vez que usamos el comando FETCH. Los posibles valores que puede retornar esta función son:
0: Indica que se retorno una fila en el ultimo FETCH.
-1: Indica que el ultimo FETCH no retornó ningún resultado debido a que ya no hay mas filas.
-2: Indica que la ultima fila que se iba a retornar ya no existe por que se eliminó.Es importante hacer el primer FETCH antes del WHILE para que la función @@FETCH_STATUS obtenga un resultado positivo.
Podemos ver un ejemplo?
Por supuesto!, a continuación resolveremos el siguiente enunciado empleando un cursor en SQL Server:
Transfiera el nombre y el salario de la tabla EMPLEADO, donde el salario es mayor o igual a 2500, en una nueva tabla llamada TOPE_NOMINA.
Miremos la implementación de la solución:-- Nueva tabla TOPE_NOMINA
CREATE TABLE TOPE_NOMINA(
ID INT NOT NULL IDENTITY PRIMARY KEY,
NOMBRE VARCHAR(100) NOT NULL,
SALARIO INT NOT NULL
);
BEGIN;
-- Variables para obtencion de datos en el cursor
DECLARE @EMP_NOMBRE VARCHAR(100), @EMP_SALARIO INT;
-- Declaración del cursor
DECLARE cursor_emp CURSOR STATIC
FOR SELECT NOMBRE, SALARIO
FROM EMPLEADO
WHERE SALARIO>=2500;
-- Apertura del cursor
OPEN cursor_emp;
-- Primer resultado del FETCH
FETCH cursor_emp INTO @EMP_NOMBRE, @EMP_SALARIO;
--Bucle de lectura
WHILE (@@FETCH_STATUS = 0 )
BEGIN;
-- Transferir los registros a la nueva tabla
INSERT INTO TOPE_NOMINA (NOMBRE, SALARIO)
VALUES (@EMP_NOMBRE,@EMP_SALARIO);
-- enesima iteración sobre el cursor
FETCH cursor_emp INTO @EMP_NOMBRE, @EMP_SALARIO;
END;
-- Cierre del cursor
CLOSE cursor_emp;
-- Limpieza
DEALLOCATE cursor_emp;
END;
El código anterior implementa un bucle WHILE que se ejecuta solo si la función @@FETCH_STATUS es igual a cero, es decir, si aun quedan resultados a los que referenciar con el cursor.
James Revelo Urrea - Desarrollador independiente http://www.hermosaprogramacion.com