Cursores – Casos prácticos

Cursores

Elemento que almacena en memoria el resultado de un Select. Para mayor información ver Cursores en SQL Server

Pasos:

  1. Declarar el cursor, utilizando DECLARE
  2. Abrir el cursor, utilizando OPEN
  3. Leer los datos del cursor, utilizando FETCH … INTO
  4. Cerrar el cursor, utilizando CLOSE
  5. Liberar el cursor, utilizando DEALLOCATE

Las sintaxis de las instrucciones es como sigue:

DECLARE <NOMBRE_CURSOR> CURSOR FOR <SENTENCIA_SQL>

OPEN <NOMBRE_CURSOR>

FETCH <NOMBRE_CURSOR> INTO <LISTA_VARIABLES>

WHILE (@@FETCH_STATUS = 0)
BEGIN
FETCH <NOMBRE_CURSOR> INTO <LISTA_VARIABLES>

END — FIN DEL BUCLE WHILE

CLOSE <NOMBRE_CURSOR>

DEALLOCATE <NOMBRE_CURSOR>



 

Ejercicios

Cursor que liste las categorias, el resultado se muestra como sigue:
1 Beverages
2 Condiments
3 Confections
4 Dairy Products
5 Grains/Cereals
6 Meat/Poultry
7 Produce
8 Seafood */

Crear y mostrar los resultados manualmente.
Declare cursorCategorias Cursor for select CategoryID, CategoryName from Categories
go
Abrir
Open cursorCategorias
go
Para mostrar las categorías usar la siguiente instrucción, repetir hasta terminar el listado.
Fetch cursorCategorias
go
select @@FETCH_STATUS — 0 cuando existen registros por leer, -1 cuando ya no existen registros
go
Cerrar el cursor
close cursorCategorias
Liberar el cursor de la memoria.
Deallocate cursorCategorias
go

Listado automático usando While y variables

Declare cursorCategorias Cursor for select CategoryID, CategoryName from Categories
Open cursorCategorias
Declare @CodigoCategoria int, @NombreCategoria nvarchar(15)
Fetch cursorCategorias into @CodigoCategoria, @NombreCategoria
WHILE (@@FETCH_STATUS = 0)
BEGIN
Print ‘Código: ‘ + Ltrim(Str(@CodigoCategoria)) + Space(2)
+ ‘Nombre: ‘ + @NombreCategoria
Fetch cursorCategorias into @CodigoCategoria, @NombreCategoria
END — FIN DEL BUCLE WHILE
CLOSE cursorCategorias
DEALLOCATE cursorCategorias
go

El resultado se muestra en la imagen.

En el ejemplo siguiente, actualizamos el precio de los productos: si su stock es mayor
o igual a 1000, se descuenta el precio al 50%, sino se descuenta el precio al 20%. 

DECLARACIÓN DEL CURSOR DE ACTUALIZACION

DECLARE ActualizaPreciosProductos CURSOR FOR
SELECT ProductID, ProductName, UnitPrice, UnitsInStock FROM Products
FOR UPDATE
— APERTURA DEL CURSOR
OPEN ActualizaPreciosProductos
— DECLARACION DE VARIABLES PARA EL CURSOR
DECLARE @ID INT, @NOMBRE VARCHAR(255), @PRECIO DECIMAL, @StockActual INT
— LECTURA DE LA PRIMERA FILA DEL CURSOR
FETCH ActualizaPreciosProductos INTO @ID, @NOMBRE, @PRECIO, @StockActual
— MIENTRAS PUEDA LEER EL REGIStockActualRO
WHILE (@@FETCH_Status = 0 )
BEGIN
IF(@StockActual>=100)
Begin
SET @PRECIO = 0.5*@PRECIO
End
ELSE
Begin
SET @PRECIO = 0.80*@PRECIO
End
UPDATE Products SET UnitPrice = @PRECIO
WHERE CURRENT OF ActualizaPreciosProductos
–IMPRIMIR
PRINT ‘EL PRECIO DE PRODUCTO ‘+ @NOMBRE+ ‘ ES ‘ + Str(@PRECIO)
— LECTURA DE LA SIGUIENTE FILA DEL CURSOR
FETCH ActualizaPreciosProductos INTO @ID, @NOMBRE, @PRECIO, @StockActual
END
— CIERRE DEL CURSOR
CLOSE ActualizaPreciosProductos
— LIBERAR LOS RECURSOS
DEALLOCATE ActualizaPreciosProductos
go

CURSORES ANIDADOS
Cursor que muestre las categorías y de cada categoría los productos

Declare cursorCategorias cursor for select CategoryID, CategoryName from Categories
Open cursorCategorias
Declare @CodigoCategoria int, @NombreCategoria nvarchar(15)
Fetch cursorCategorias into @CodigoCategoria, @NombreCategoria
While (@@FETCH_STATUS = 0)
Begin
Print ‘=========================================================================================’
Print ‘Código: ‘ + Ltrim(Str(@CodigoCategoria)) + Space(3) + ‘ Categoria: ‘ + @NombreCategoria
Print ‘=========================================================================================’
— Crear el cursor para leer los productos de la categoría actual
Declare cursorProductosPorCategoria cursor for
select ProductID, ProductName, UnitPrice from Products where CategoryID = @CodigoCategoria
Open cursorProductosPorCategoria
Declare @CodigoProducto int, @NombreProducto nvarchar(40),@Precio Decimal
Fetch cursorProductosPorCategoria into @CodigoProducto , @NombreProducto ,@Precio
While (@@FETCH_STATUS = 0)
Begin
Print ‘Código: ‘ + Ltrim(Str(@CodigoProducto)) + Space (3) + ‘Descripción: ‘ + @NombreProducto
Fetch cursorProductosPorCategoria into @CodigoProducto , @NombreProducto ,@Precio
End
Close cursorProductosPorCategoria
Deallocate cursorProductosPorCategoria
Fetch cursorCategorias into @CodigoCategoria, @NombreCategoria
End
close cursorCategorias
Deallocate cursorCategorias
go

El resultado con las dos primeras categorías y sus productos se muestran en la imagen siguiente:

 



 

Cursor Scroll: 

Para leer los datos del cursor definido como Scroll, en la instrucción Fetch se puede usar las siguientes palabras para desplazarse.

— First – Primer registro
— Last – Último registro
— Next – Siguiente Registro
— Prior – Registro Anterior
— Relative n – Positivo Avanza n
— Negativo Retrocede n
— Absolute n – Registro n

— NO OLVIDAR USAR LA CLAUSULA…. FROM

— Crear un cursor Scroll con las categorias
Declare cursorScrollCategorias Scroll Cursor for select * from Categories
Open cursorScrollCategorias
go
— Recién abierto… la siguiente instrucción lee el primer registro
Fetch cursorScrollCategorias
go
— Primero
Fetch First from cursorScrollCategorias
go

— Último
Fetch Last from cursorScrollCategorias
go
— Retroceder 3
Fetch Relative -3 from cursorScrollCategorias
go

— Al número 6
Fetch Absolute 6 from cursorScrollCategorias
go
— Siguiente
Fetch next from cursorScrollCategorias
go
— Anterior
Fetch prior from cursorScrollCategorias
go
— Cerrar y liberar
Close cursorScrollCategorias
Deallocate cursorScrollCategorias
go