Cursores en SQL Server

Manejo de cursores en SQL Server



En este artículo estaremos hablando de un tema muy importante ya que a medida que nos adentramos en el mundo de la base de datos y empezamos a crear querys se nos resulta muy complicado muchas veces recorrer amplios volúmenes de registros, inclusive modificar esos registros es un dolor de cabezas, bueno este articulo lo hemos preparado para hablar sobre los Cursores aunque leerás en muchos otros post que no son recomendable usarlos(Sino SQL Server ya no permitiría seguirlos creando como muchas otras funciones que han quedado obsoletas) te digo todo lo contrario ya que pueden ser muy útiles cuando necesitamos crear algunos mecanismos que no podemos hacerlos mediante otra vía.


¿Qué es un Cursor?

Los cursores son un conjunto de instrucciones T-SQL que nos permiten recorrer fila a fila los registros de una tabla. mediante un cursor podemos leer y modificar los datos almacenados en una tabla.


Sintaxis

Un cursor lo podemos crear a partir de la siguiente sintaxis:

DECLARE @Valor TipoDato, @Valor2 TipoDato;
DECLARE NombreCursor CURSOR FOR
SELECT Columna1,Columna2 FROM Nombre_Tabla;

OPEN NombreCursor
 FETCH NEXT NombreCursor INTO @Valor1, @Valor2
 WHILE @@FETCH_STATUS = 0
 BEGIN
  Instruccion T-SQL

  FETCH NEXT FROM NombreCursor INTO @Valor1,@Valor2
 END

 CLOSE NombreCursor
 DEALLOCATE NombreCursor 

A continuación vamos a explicar la estructura de un cursor:

DECLARE @Valor TipoDato, @Valor2 TipoDato;

Mediante la palabra clave DECLARE, declaramos las variables y el tipo de datos que vamos a utilizar. Debemos saber que el tipo de dato declarado tiene que ser el mismo del campo existente en la tabla.

DECLARE NombreCursor CURSOR FOR
SELECT Columna1,Columna2 FROM Nombre_Tabla; 

Para declarar un cursor debemos hacer uso de la palabra clave DECLARE  seguido del nombre del cursor y por último agregamos la palabra clave CURSOR FOR. Seguidamente creamos una sentencia select para leer los registros almacenados en la tabla.

OPEN NombreCursor

OPEN CURSOR nos indica que abrimos la instrucción del cursor.

FETCH NEXT NombreCursor INTO @Valor1, @Valor2

La instrucción FETCH NEXT  nos permite recorrer los registros en la tabla leída, y mediante la sentencia INTO los valores recorridos son almacenados en las variables declaradas para el cursor.

Acá debemos de tener en cuenta que la cantidad de columnas leídas deben ser igual ala cantidad de variables declaradas en el cursor y las debemos ordenar en el mismo orden tanto en la sentencia select de la tabla como en la declaración del cursor. Si la cantidad de columnas seleccionadas en la tabla fueron 10 entonces debemos declarar 10 variables para el cursor.

WHILE @@FETCH_STATUS = 0

Mediante la variable @@FETCH_STATUS podemos saber si hay un próximo registro por recorrer o si ya hemos llegado al límite de la lectura de los registros. Si la lectura de todo los registros ha sido correcta la variable tomará un valor igual a cero.

BEGIN
  Instruccion T-SQL

  FETCH NEXT FROM NombreCursor INTO @Valor1,@Valor2
 END 

Después de haber declarado la variable @@FETCH_STATUS podemos declarar bloques de sentencia u operación T-SQL (INSERT, UPDATE, DELETE) que se ejecuten a partir de los registros seleccionados de la tabla. Posterior a eso la instrucción FETCH NEXT FROM nos permite continuar con los siguientes registros almacenados obtenidos a partir de las columnas seleccionadas y almacenadas en cada variable del cursor.

 CLOSE NombreCursor
 DEALLOCATE NombreCursor 

La instrucción CLOSE NombreCursor no indica que los registros tomados por el cursor son liberados. de modo que una vez que el cursor es cerrado este ya no podrá recorrer los registros de la tabla hasta que sea abierto nuevamente. Por último, la instrucción DEALLOCATE nos indica que se eliminara la referencia definida al cursor lo nos dice que ya no podremos hacer una reapertura de dicho cursor.


Tipos de Cursores

Existen 4 tipos de cursores que podemos crear en SQL Server los cuales puede ser cursores estáticos (STATIC), cursores predeterminados (FAST_FORWARD), cursores Dinámicos (DINAMIC) y cursores de conjunto de llaves (KEYSET).

  • Cursores estáticos (STATIC): este tipo de cursores cargan el conjunto de registros al momento de la creación del cursor y el resultado obtenido es almacenado en caché durante todo el periodo de vida útil del cursor creado. Los cursores estáticos pueden moverse en orientación hacia adelante y hacia atrás.
  • Cursores predeterminados (FAST_FORWARD): Este tipo de curso suele ser idéntico a los cursores estático con la única diferencia que este se suele moverse únicamente hacia adelante.
  • Cursores Dinámicos (DINAMIC): En este tipo de cursores las operaciones en la tabla puede ser visibles siempre y cuando el cursor se encuentre abierto.
  • Cursores de conjunto de llaves (KEYSET): Este tipo de cursores suelen moverse únicamente de la primera a la última fila y viceversa. las filas recorridas en este tipo de cursor suelen ser almacenadas en una tabla temporal como por ejemplo en la base de datos TEMPDB.

Alcance de un cursor

Al utilizar cursores debemos saber hasta dónde podemos llegar, para ello podemos hacer uso de dos palabras claves las cuales son GLOBAL Y LOCAL las cuales son escritas luego de declarar el cursor.

DECLARE CURSOR NombreCursor [GLOBAL]
DECLARE CURSOR NombreCursor [LOCAL]

Al declarar un cursor como GLOBAL, este podemos utilizarlo en cualquier momento y podemos hacer su llamado desde cualquier procedimiento almacenado, trigger o funciones creadas.

El cursor declarado como LOCAL especifica que este es solamente utilizable para el procedimiento almacenado, trigger o función donde ha sido creado.


Ejemplos de cursores en SQL Server

Vista la teoría y explicación de la sintaxis de un cursor a continuación, vamos a crear una serie de ejemplo de cómo crear un cursor.

Para el primer ejemplo vamos a crear un cursor el cual recorrerá una tabla que contiene registros de productos y nos imprima un mensaje en pantalla del nombre del producto y la marca. el codigo creado para el cursor será el siguiente:

DECLARE ProductoMarca CURSOR FOR
SELECT NombreProducto,Marca FROM SivProductos WHERE activo = 1
OPEN ProductoMarca
FETCH NEXT FROM  ProductoMarca INTO @Nombre,@Marca
WHILE @@FETCH_STATUS = 0
 BEGIN
  PRINT @Nombre+' | '+@Marca
  FETCH NEXT FROM ProductoMarca INTO @Nombre,@Marca
 END
 CLOSE ProductoMarca
 DEALLOCATE ProductoMarca

La Figura anterior nos muestra un cursor el cual recorre una tabla llamada "SivProductos", de la cual el cursor lee las columnas "NombreProducto" y "Marca" de los productos que estén activos en el catálogo y nos imprime un mensaje con el nombre del producto y la marca concatenados.(Puede que te interese saber sobre: cómo concatenar texto y columnas en SQL Server). Ejecutemos el cursor en SQL Server Management Studio.



Si ejecutamos el cursor podemos observar que se nos va imprimir el resultado de todo los productos y su respectiva marca concatenados a manera de un mensaje.


Cursor para actualizar en SQL Server

Ahora vamos a crear un procedimiento almacenado que utiliza un cursor para actualizar las existencias de productos a partir de una compra. veamos la consulta que vamos a crear:

CREATE PROCEDURE ActualizarStock
@CompraID as bigint
AS
BEGIN
		declare @Producto nvarchar(25),
		         @ProductoCantidad decimal(18,2)
	--creamos el proceso que actualizara los registros de los productos asociados ala compra
	 declare IniciarActualizacionProd cursor for
	  select objProductoID,CantidadComprada+CantidadBonificada from ScpCompraProducto where objCompraID = @CompraID
	   open IniciarActualizacionProd
		fetch next from IniciarActualizacionProd into @Producto,@ProductoCantidad
		 while @@FETCH_STATUS = 0
		   begin 
		   --procedemos a actualizar los registros de los productos
		    update SivProductos
			 set 
			 CantidadExistente = CantidadExistente-@ProductoCantidad
			 where ProductoID = @Producto
		   ---continuamos con el siguiente registro
		 fetch next from IniciarActualizacionProd into @Producto,@ProductoCantidad
		end
	 close IniciarActualizacionProd
	deallocate IniciarActualizacionProd
END 

El procedimiento almacenado que hemos creado recorrerá la tabla para seleccionar los productos a los cuales actualizaremos las existencias. Al procedimiento almacenado le hemos declarado una variable con la cual la sentencia Select seleccionará los productos asociados a ese codigo de compra. Veamos la consulta en SQL Server management Studio:


Si observamos el cursor ha sido creado y ahora podemos ejecutarlo para probar si se actualiza los registros para eso debemos ejecutar el procedimiento almacenado(Te puede interesar: Procedimientos almacenados en SQL Server).
 EXEC ActualizarStock 10001 

Mediante la  figura anterior podemos ejecutar el procedimiento almacenado y actualizar los productos incluidos en una compra.

Los cursores son herramientas muy útiles y poderosas que en muchas ocasiones nos pueden resolver muchos problemas al trabajar con transacciones y volúmenes de datos amplios. hasta acá con este artículo de cursores será en otro artículo profundizar mucho más de este tema ya que es muy amplio dada su utilidad.


Publicar un comentario

0 Comentarios