Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » SQL Server »

Reemplazar Cursor SQL

Estas en el tema de Reemplazar Cursor SQL en el foro de SQL Server en Foros del Web. Buen día. Me encuentro en un dilema y es que en el lugar donde actualmente trabajo utilizo mucho SQL y me han pedido optimizar unos ...
  #1 (permalink)  
Antiguo 23/06/2015, 10:02
 
Fecha de Ingreso: junio-2015
Mensajes: 2
Antigüedad: 8 años, 10 meses
Puntos: 0
Reemplazar Cursor SQL

Buen día.

Me encuentro en un dilema y es que en el lugar donde actualmente trabajo utilizo mucho SQL y me han pedido optimizar unos procesos ya que la cantidad de información que se maneja es bastante, hay un proceso que esta basado en un cursor y necesito optimizarlo ya que estos son muy lentos y mas cuando se maneja mucha información.

Este es el código

Código SQL:
Ver original
  1. USE [STREAMS]
  2. GO
  3. /****** Object:  StoredProcedure [dbo].[morasconsumoultimos12]    Script Date: 06/23/2015 10:22:42 ******/
  4. SET ANSI_NULLS OFF
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. ALTER PROCEDURE [dbo].[morasconsumoultimos12]
  9.                    
  10.  
  11. AS
  12.  
  13. DECLARE @mora30 INT,@mora60 INT,@mora90 INT,@morama90 INT,@contador INT, @SQL VARCHAR(100)
  14.  
  15. DECLARE @LNNOTE FLOAT,  
  16. @DPD1 INT,@DPD2 INT,@DPD3 INT,@DPD4 INT,@DPD5 INT,@DPD6 INT,@DPD7 INT,
  17. @DPD8 INT,@DPD9 INT,@DPD10 INT,@DPD11 INT,@DPD12 INT
  18.  
  19.  
  20. DECLARE curs_mora cursor
  21. FOR
  22. SELECT LNNOTE
  23. ,DPD1405,DPD1406,DPD1407 ,DPD1408 ,DPD1409,DPD1410 ,DPD1411,DPD1412
  24. ,DPD1501,DPD1502,DPD1503, DPD1504   FROM Bstringconsumolina
  25.  
  26. OPEN curs_mora
  27. fetch NEXT FROM curs_mora INTO @LNNOTE,@DPD1,@DPD2,@DPD3,@DPD4,@DPD5,@DPD6,
  28. @DPD7,@DPD8,@DPD9,@DPD10,@DPD11,@DPD12
  29.  
  30. while @@fetch_status=0
  31. BEGIN
  32.     SET @mora30=0
  33.     SET @mora60=0
  34.     SET @mora90=0
  35.     SET @morama90=0
  36.     --set @contador=1
  37.     --while @contador<7
  38.     --Begin
  39.         --set @sql= 'case when @CBCUV70' + CONVERT (VARCHAR,@contador) + '>30 THEN  @mora +1 ELSE 0 END'
  40.  
  41.         SET @mora30= CASE WHEN @DPD12 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  42.         SET @mora60= CASE WHEN @DPD12 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  43.         SET @mora90= CASE WHEN @DPD12 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  44.         SET @morama90= CASE WHEN @DPD12 > 90  THEN  @morama90 +1 ELSE @morama90 END
  45.  
  46.         SET @mora30= CASE WHEN @DPD11 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  47.         SET @mora60= CASE WHEN @DPD11 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  48.         SET @mora90= CASE WHEN @DPD11 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  49.         SET @morama90= CASE WHEN @DPD11 > 90  THEN  @morama90 +1 ELSE @morama90 END
  50.  
  51.         SET @mora30= CASE WHEN @DPD10 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  52.         SET @mora60= CASE WHEN @DPD10 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  53.         SET @mora90= CASE WHEN @DPD10 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  54.         SET @morama90= CASE WHEN @DPD10 > 90  THEN  @morama90 +1 ELSE @morama90 END
  55.  
  56.         SET @mora30= CASE WHEN @DPD9 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  57.         SET @mora60= CASE WHEN @DPD9 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  58.         SET @mora90= CASE WHEN @DPD9 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  59.         SET @morama90= CASE WHEN @DPD9 > 90  THEN  @morama90 +1 ELSE @morama90 END
  60.  
  61.         SET @mora30= CASE WHEN @DPD8 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  62.         SET @mora60= CASE WHEN @DPD8 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  63.         SET @mora90= CASE WHEN @DPD8 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  64.         SET @morama90= CASE WHEN @DPD8 > 90  THEN  @morama90 +1 ELSE @morama90 END
  65.  
  66.         SET @mora30= CASE WHEN @DPD7 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  67.         SET @mora60= CASE WHEN @DPD7 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  68.         SET @mora90= CASE WHEN @DPD7 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  69.         SET @morama90= CASE WHEN @DPD7 > 90  THEN  @morama90 +1 ELSE @morama90 END
  70.  
  71.         SET @mora30= CASE WHEN @DPD6 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  72.         SET @mora60= CASE WHEN @DPD6 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  73.         SET @mora90= CASE WHEN @DPD6 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  74.         SET @morama90= CASE WHEN @DPD6 > 90  THEN  @morama90 +1 ELSE @morama90 END
  75.  
  76.         SET @mora30= CASE WHEN @DPD5 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  77.         SET @mora60= CASE WHEN @DPD5 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  78.         SET @mora90= CASE WHEN @DPD5 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  79.         SET @morama90= CASE WHEN @DPD5 > 90  THEN  @morama90 +1 ELSE @morama90 END
  80.  
  81.         SET @mora30= CASE WHEN @DPD4 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  82.         SET @mora60= CASE WHEN @DPD4 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  83.         SET @mora90= CASE WHEN @DPD4 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  84.         SET @morama90= CASE WHEN @DPD4 > 90  THEN  @morama90 +1 ELSE @morama90 END
  85.  
  86.         SET @mora30= CASE WHEN @DPD3 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  87.         SET @mora60= CASE WHEN @DPD3 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  88.         SET @mora90= CASE WHEN @DPD3 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  89.         SET @morama90= CASE WHEN @DPD3 > 90  THEN  @morama90 +1 ELSE @morama90 END
  90.  
  91.         SET @mora30= CASE WHEN @DPD2 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  92.         SET @mora60= CASE WHEN @DPD2 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  93.         SET @mora90= CASE WHEN @DPD2 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  94.         SET @morama90= CASE WHEN @DPD2 > 90  THEN  @morama90 +1 ELSE @morama90 END
  95.  
  96.         SET @mora30= CASE WHEN @DPD1 BETWEEN 1 AND 30   THEN  @mora30 +1 ELSE @mora30 END
  97.         SET @mora60= CASE WHEN @DPD1 BETWEEN 31 AND 60  THEN  @mora60 +1 ELSE @mora60 END
  98.         SET @mora90= CASE WHEN @DPD1 BETWEEN 61 AND 90  THEN  @mora90 +1 ELSE @mora90 END
  99.         SET @morama90= CASE WHEN @DPD1 > 90  THEN  @morama90 +1 ELSE @morama90 END
  100.                
  101.                                
  102.            
  103.                          --SET @contador=@contador+1
  104.     --END
  105.    
  106.     UPDATE Bstringconsumolina SET mora30 = @mora30  WHERE  CURRENT OF curs_mora
  107.     UPDATE Bstringconsumolina SET mora60 = @mora60  WHERE CURRENT OF curs_mora
  108.     UPDATE Bstringconsumolina SET mora90 = @mora90  WHERE CURRENT OF curs_mora
  109.     UPDATE Bstringconsumolina SET mora_mayor90 = @morama90  WHERE CURRENT OF curs_mora
  110.  
  111. fetch NEXT FROM curs_mora INTO @LNNOTE,@DPD1,@DPD2,@DPD3,@DPD4,@DPD5,@DPD6,
  112. @DPD7,@DPD8,@DPD9,@DPD10,@DPD11,@DPD12
  113.  
  114. END
  115. close curs_mora
  116. deallocate curs_mora
Cabe aclarar que:

La tabla 'Bstringconsumolina' fue previamente creada antes de que se ejecute el cursor, luego de ello se modifica la tabla y se añade las columnas de mora:

Código SQL:
Ver original
  1. ALTER TABLE Bstringconsumolina ADD mora30 INT, mora60 INT, mora90 INT,mora_mayor90 INT

luego de esto se ejecuta el cursor, pero toma mucho tiempo, podrían darme sugerencias de como optimizar este cursor

Gracias.

Última edición por gnzsoloyo; 23/06/2015 a las 10:26
  #2 (permalink)  
Antiguo 23/06/2015, 11:12
Avatar de iislas
Colaborador
 
Fecha de Ingreso: julio-2007
Ubicación: Mexico, D.F.
Mensajes: 6.482
Antigüedad: 16 años, 9 meses
Puntos: 180
Respuesta: Reemplazar Cursor SQL

Los cursores no son lentos, hacen que se alenté la respuesta del servidor, ya que se crean en memoria.

Debes declarar tu VARIABLE - TABLA y ahí, insertar los registros que obtienes de esta consulta

Código SQL:
Ver original
  1. SELECT LNNOTE
  2.  
  3. 23.,DPD1405,DPD1406,DPD1407 ,DPD1408 ,DPD1409,DPD1410 ,DPD1411,DPD1412
  4.  
  5. 24.,DPD1501,DPD1502,DPD1503, DPD1504   FROM Bstringconsumolina

Después, simplemente recorres tu variable-tabla, mediante el While correspondiente.

Recuerda que a tu variable-tabla, le puede crear índices para que te de una mejor respuesta.
__________________
MCTS Isaias Islas
  #3 (permalink)  
Antiguo 24/06/2015, 07:26
 
Fecha de Ingreso: junio-2015
Mensajes: 2
Antigüedad: 8 años, 10 meses
Puntos: 0
Respuesta: Reemplazar Cursor SQL

Podrías ayudarme con algún ejemplo, o como abordar esta solución... Si no es molestia.

Gracias...
  #4 (permalink)  
Antiguo 24/06/2015, 09:51
Avatar de iislas
Colaborador
 
Fecha de Ingreso: julio-2007
Ubicación: Mexico, D.F.
Mensajes: 6.482
Antigüedad: 16 años, 9 meses
Puntos: 180
Respuesta: Reemplazar Cursor SQL

Si vas a SAN GOOGLE y buscas, encontraras ejemplos, como este:

1. Create a temp table with an identity column that auto-increments, starting at 1 and going up by 1.
Código SQL:
Ver original
  1. CREATE TABLE #Temp1 (
  2.      ID INT IDENTITY(1,1),
  3.      ItemName VARCHAR(50),
  4.      ItemDescription VARCHAR(50)
  5.    ) .

2. Get the data inserted for review (you do not need to insert the ID field, it is being inserted with numbers increasing by 1 and starting at 1).
Código SQL:
Ver original
  1. INSERT INTO #Temp1(
  2.      ItemName,
  3.      ItemDescription
  4.    )
  5.    SELECT ItemName,
  6.      ItemDescription
  7.    FROM InventoryTable .

3. Create the loop and cycle through the data.
Código SQL:
Ver original
  1. DECLARE @Counter INT
  2.    SET @Counter = 1
  3.  
  4.    DECLARE @ItemReview VARCHAR(50)
  5.  
  6.    WHILE @Counter <= (SELECT COUNT(*) FROM InventoryTable)
  7.    BEGIN
  8.      SELECT @ItemReview = t.ItemName
  9.      FROM #Temp1 t
  10.      WHERE t.ID = @Counter
  11.  
  12.      IF @ItemReview = 'Tomatoes'
  13.      BEGIN
  14.          Do something here&#8230;.
  15.      END
  16.  
  17.      SET @Counter = @Counter + 1
  18.  
  19.    END
__________________
MCTS Isaias Islas
  #5 (permalink)  
Antiguo 24/06/2015, 12:30
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 17 años, 8 meses
Puntos: 774
Respuesta: Reemplazar Cursor SQL

deja de que busque en google, que busque en el foro hay cantidad de ejemplos con while......
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #6 (permalink)  
Antiguo 24/06/2015, 15:09
Avatar de iislas
Colaborador
 
Fecha de Ingreso: julio-2007
Ubicación: Mexico, D.F.
Mensajes: 6.482
Antigüedad: 16 años, 9 meses
Puntos: 180
Respuesta: Reemplazar Cursor SQL

EXACTO !!!, aquí en el foro incluso, se formo un grupo ANTI-CURSORES, si no mal recuerdo....
__________________
MCTS Isaias Islas
  #7 (permalink)  
Antiguo 28/06/2015, 13:59
 
Fecha de Ingreso: junio-2015
Ubicación: Bogota
Mensajes: 18
Antigüedad: 8 años, 10 meses
Puntos: 0
Respuesta: Reemplazar Cursor SQL

Señores... Eso es una respuesta? Si bien la pregunta no está bien formulada tampoco, el decir "vaya busque en otro lado" no ayuda a nada. Por favor... No digan como NO se hace. Eso han esta claro... Como está no es la manera correcta... La idea es encontrarla.

Que es lo que se supone que hace el cursor. No en palabras de desarrollador sino en palabras de usuario?
  #8 (permalink)  
Antiguo 29/06/2015, 10:50
Avatar de iislas
Colaborador
 
Fecha de Ingreso: julio-2007
Ubicación: Mexico, D.F.
Mensajes: 6.482
Antigüedad: 16 años, 9 meses
Puntos: 180
Respuesta: Reemplazar Cursor SQL

P_III, lo que siempre pedidos a los compañeros que visitan este y otros foros, que PRIMERO pongan de su parte y busquen en la red (GOOGLE) para resolver su problema, si no encuentran como hacerlo, acudan a los foros con PREGUNTAS CONCRETAS, no como algunas que rondan por estos foros ("quiero hacer un sistema de inventarios, que hago?", "tengo estas preguntas (de examen), me las contestan?").

No es que no se quiera contestar

Puse un ejemplo, ¿sirvió?
__________________
MCTS Isaias Islas
  #9 (permalink)  
Antiguo 30/06/2015, 07:48
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 17 años, 8 meses
Puntos: 774
Respuesta: Reemplazar Cursor SQL

Un cursor carga los datos de una consulta en memoria, y hay ocasiones en que consume memoria de mas y puede llegar a causar problemas en el servidor de bases de datos, por lo que no es recomendable usar un cursor, ahora en lo que comentas de que asi no se debe de contestar, estoy de acuerdo, pero tambien pon un poco de tu parte, te dieron un ejemplo que se encuentra en muchisimos lados de este foro, en ningun momento comentaste que ya habias buscado ni que habias encontrado.....
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me

Etiquetas: cursor, reemplazar, select, sql, tabla
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 10:51.