2014/04/17

CURSOR en SQL SERVER

Para algunos, es una herramienta útil, lo único cierto es que rompe con uno de los fundamentos con los que SQL SERVER trabaja que es la Teoría de conjuntos, por lo tanto muchos recomiendan no utilizarlo a menos que sea sumamente necesario y no tengamos otra opción para resolver el problema que se nos presenta. Hasta ahora, en lo personal, he logrado solventar todos los problemas donde anteriormente se usaban cursores con consultas SQL y el tiempo de respuesta se ha visto incrementado enormemente.

El funcionamiento es similar a una iteración como DO..WHILE, WHILE, etc en los lenguajes de programación, solo que necesitamos de una consulta. Nuevamente usaré AdventureWorks2012 para el ejemplo:

USE AdventureWorks2012;
--Declaramos las variables que utilizaremos
DECLARE @c TINYINT = 1, @a TINYINT=1
--Variable para almacenar los valores del primer CURSOR
             ,@businessEntityID INT
             , @creditCardID INT
             , @modifiedDate DATETIME
--Variables para almacenar los valores del segundo CURSOR
             , @cardType VARCHAR(100)
             , @cardNumber VARCHAR(25)
             , @expMonth TINYINT
             , @expYear SMALLINT
             , @modifiedDate2 DATETIME

--Declaración del CURSOR cPersonCreditCard
DECLARE cPersonCreditCard CURSOR FOR
SELECT TOP 20 * FROM sales.PersonCreditCard

--Abrimos el CURSOR cPersonCreditCard
OPEN cPersonCreditCard

--FETCH para moverse entre las filas del resultado del CURSOR.
FETCH NEXT FROM cPersonCreditCard
--INTO para almacenar los valores del resultado del CURSOR en las variables indicadas.
--La cantidad de variables debe ser la misma que la cantidad de columnas devueltas por
--el cursor así como los tipos de datos deben ser similares o idénticos.
INTO @businessEntityID, @creditCardID, @modifiedDate

--Iniciamos con la iteración preguntando si existen filas en el CURSOR
--0 indica que el resultado de la instrucción FETCH se ejecutó correctamente.
WHILE @@FETCH_STATUS = 0
BEGIN
       --Imprimimos las variables para ver el resultado.
       PRINT '< Cursor cPersonCreditCard: ' + CAST( @c AS VARCHAR )
       PRINT '@businessEntityID:' + CAST( @businessEntityID AS VARCHAR )
       PRINT '@creditCardID: ' + CAST( @creditCardID AS VARCHAR )
       PRINT '@modifiedDate: ' + CAST( @modifiedDate AS VARCHAR )

       SET @c=@c+1
       SET @a=1
      
       --CURSOR ANIDADO cCreditCard para obtener otros valores.
       DECLARE cCreditCard CURSOR FOR
       SELECT CardType, CardNumber, ExpMonth, ExpYear, ModifiedDate
       FROM sales.CreditCard WHERE CreditCardID = @creditCardID

       --Abrimos el CURSOR cCreditCard
       OPEN cCreditCard

             --Nos posicionamos en la primera fila.
             FETCH NEXT FROM cCreditCard
             INTO @cardType, @cardNumber, @expMonth, @expYear, @modifiedDate2
            
             --Verificamos que la instrucción FETCH se haya ejecutado correctamente.
             WHILE @@FETCH_STATUS = 0
             BEGIN
                    --Imprimimos las variables del cursor cCreditCard
                    PRINT '   <<<Cursor cCreditCard: ' + CAST( @a AS VARCHAR )
                    PRINT '   @cardType:' + CAST( @cardType AS VARCHAR )
                    PRINT '   @cardNumber: ' + CAST( @cardNumber AS VARCHAR )
                    PRINT '   @expMonth: ' + CAST( @expMonth AS VARCHAR )
                    PRINT '   @expYear:' + CAST( @expYear AS VARCHAR )
                    PRINT '   @modifiedDate2: ' + CAST( @modifiedDate2 AS VARCHAR )
                    PRINT '   >>>>>'
                    SET @a=@a+1
                    --Nos movemos hacia la siguiente fila del CURSOR cCreditCard
                    FETCH NEXT FROM cCreditCard
                    INTO @cardType, @cardNumber, @expMonth, @expYear, @modifiedDate2
             END -- Fin de la iteración del CURSOR cCreditCard
             CLOSE cCreditCard; --Cerramos el CURSOR cCreditCard
             DEALLOCATE cCreditCard; --Liberamos el CURSOR

       PRINT '>>>>>>>>'

       --Nos movemos hacia la siguiente fila del CURSOR cPersonCreditCard
       FETCH NEXT FROM cPersonCreditCard
       INTO @creditCardID, @creditCardID, @modifiedDate
END -- Fin de la iteración del CURSOR cPersonCreditCard
CLOSE cPersonCreditCard; --Cerramos el CURSOR cPersonCreditCard

DEALLOCATE cPersonCreditCard; --Liberamos el CURSOR cPersonCreditCard

Mi recomendación, solo utilícenlo como ultimo recurso, debemos acostumbrarnos a las buenas prácticas y pensar en el resultado como un conjunto de datos.

SALUDOS!
COMPARTE ESTA INFORMACION SI TE PARECIO INTERESANTE

0 comentarios:

Publicar un comentario