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

Cambiar cursor por Funcion

Estas en el tema de Cambiar cursor por Funcion en el foro de SQL Server en Foros del Web. HOla a todos! de nuevo tengo problemas con un cursor, bueno la cuestión es que más bien necesito cambiarlo por una función o un SP ...
  #1 (permalink)  
Antiguo 21/02/2010, 17:05
 
Fecha de Ingreso: diciembre-2009
Mensajes: 14
Antigüedad: 14 años, 4 meses
Puntos: 0
Exclamación Cambiar cursor por Funcion

HOla a todos! de nuevo tengo problemas con un cursor, bueno la cuestión es que más bien necesito cambiarlo por una función o un SP que me genere lo siguiente:

Un Folio tomando el campo de sucursal + el campo Año + un consecutivo de 7 posiciones, pero esto lo necesito por cada sucursal y por cada año, es decir:

para la sucursal 0001 año 2008 --> 0001080000001 ,0001080000002,0001080000003
para la sucursal 0001 año 2009 --> 0001090000001 ,0001090000002,0001090000003...
para la sucursal 0002 año 2007 --> 0002070000001 ,0002070000002
para la sucursal 0003 año 2009 --> 0003090000001 ,0003090000002,0003090000003...

y así sucesivamente...

Lo solucione con este cursor, pero obviamente estamuy pesado por que son 1,500,000 de registros:
Código:
BEGIN TRAN

	DECLARE @Sucursal INT
	DECLARE @Anio INT

	DECLARE Cursor1 CURSOR FOR
		SELECT DISTINCT 
			NIdSucursal,CONVERT(INT,YEAR(DEmpeno)) Anio
		FROM 
			Boletas 
		ORDER by 
			NIdSucursal,CONVERT(INT,YEAR(DEmpeno))

	OPEN Cursor1
		FETCH NEXT FROM Cursor1 
			INTO @Sucursal , @Anio 
		WHILE @@FETCH_STATUS = 0 
			BEGIN 
				CREATE TABLE #TEMPORAL 
				(
				NIdBoleta bigint,NIdSucursal bigint,VFolio char(30),Anio bigint,NuevoFolio char(30),Consecutivo bigint
				)
				INSERT INTO #TEMPORAL
					(NIdSucursal,NIdBoleta,VFolio,Anio,NuevoFolio,Consecutivo )
				SELECT 
					NIdSucursal,NIdBoleta,VFolio,YEAR(DEmpeno)Anio,
					(
					dbo.SEM_FAGREGAR_CEROS_IZQUIERDA(NIdSucursal,4)+
					dbo.SEM_FAGREGAR_CEROS_IZQUIERDA(SUBSTRING(CONVERT(VARCHAR,YEAR(DEmpeno)),3,2),2)+
					dbo.SEM_FAGREGAR_CEROS_IZQUIERDA((CASE WHEN (ROW_NUMBER() OVER(ORDER BY NIdBoleta)) IS NULL THEN 1 ELSE (ROW_NUMBER() OVER(ORDER BY NIdBoleta)) END),6)
					) NuevoFolio,
					(ROW_NUMBER() OVER(ORDER BY NIdBoleta))Consecutivo
				FROM Boletas 
				WHERE 
					NIdSucursal=@Sucursal AND
					CONVERT(INT,YEAR(DEmpeno))=@Anio 
				ORDER BY 
					NIdSucursal,YEAR(DEmpeno),NIdBoleta
				UPDATE 
					Boletas
				SET 
					Boletas.VFolio=#TEMPORAL.NuevoFolio
				FROM 
					#TEMPORAL
				WHERE 
					Boletas.NIdBoleta =#TEMPORAL.NIdBoleta AND 
					Boletas.NIdSucursal=#TEMPORAL.NIdSucursal
				DROP TABLE #TEMPORAL
				FETCH NEXT FROM Cursor1 
					INTO @Sucursal , @Anio 
				
			END 
	CLOSE Cursor1 
	DEALLOCATE Cursor1 
	SELECT 
		NIdSucursal,YEAR(DEmpeno),NIdBoleta,VFolio
	FROM 
		Boletas 
	ORDER BY 
		NIdSucursal,YEAR(DEmpeno),NIdBoleta

ROLLBACK TRAN
  #2 (permalink)  
Antiguo 22/02/2010, 00:31
Avatar de Beakdan  
Fecha de Ingreso: diciembre-2001
Ubicación: Monterrey, Nuevo León
Mensajes: 433
Antigüedad: 22 años, 4 meses
Puntos: 7
Respuesta: Cambiar cursor por Funcion

Creo que todo lo que necesitas, derivado de lo que tu consulta debe estar devolviendo es:
Código:
SELECT        NIdSucursal,
            NIdBoleta,
            YEAR(DEmpeno) AS Anio,
            (
                RIGHT(SPACE(4) + CAST(NIdSucursal AS VARCHAR(4)), 4) +
                CONVERT(VARCHAR(2), DEmpeno, 2) +
                RIGHT(SPACE(6) + CAST((ROW_NUMBER() OVER(PARTITION BY NIdSucursal, YEAR(DEmpeno) ORDER BY NIdBoleta)) AS VARCHAR(6)), 6)
            ) AS VFolio
FROM        Boletas 
ORDER BY    NIdSucursal, YEAR(DEmpeno), NIdBoleta
Algunos comentarios tengo:
Usas conversiones y validaciones innecesarias, lo cual se puede evitar verificando el tipo de dato que las funciones que usas te entregan (Year entrega siempre un INT, ROW_NUMBER() jamás es nulo).
También puedo imaginar lo que la función SEM_FAGREGAR_CEROS_IZQUIERDA hace y estoy seguro que el valor agregado de tenerla no vale el overhead de mantenerla.
Crear y destruir estructuras temporales en un bucle. Créala fuera del bucle, trúncala para reusarla, y destrúyela al salir del bucle. Y evalúa usar variables de tabla en casos como este para reducir el costo de la transacción.
Hay muy pocos problemas que justifiquen el uso de un cursor, y este no es uno de ellos. Puesto que estás usando por lo menos SQL Server 2005, considera usar mejor CTE's, funciones de ranking y cross /outer apply en combinación.
La parte que realmente debes verificar, es el uso de tus transacciones. Puedo imaginar que sea lento tu procedimiento más por el mantenimiento del log de transacciones que por cualquier otra cosa. No tiene sentido modificar la tabla si al final harás un rollback a las modificaciones de manera incondicional ¿quizá faltó publicar algo de codigo?

Última edición por Beakdan; 22/02/2010 a las 00:35 Razón: Faltaron paréntesis en código
  #3 (permalink)  
Antiguo 22/02/2010, 12:35
 
Fecha de Ingreso: diciembre-2009
Mensajes: 14
Antigüedad: 14 años, 4 meses
Puntos: 0
Respuesta: Cambiar cursor por Funcion

Hola, gracias por tu respuesta, el rollback esta demás, ese ya lo eliminé finalmente corrpi el cursor pero antes cree indices para que fuera más rápido y lo ejecute por partes, y así el tiempo se redujo notablemente, también saque la creación de la tabla temporal, eso ayudo mucho!

Muchas gracias por tu atención y colaboración!

Saludos!

Etiquetas: cursor, funcion
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 05:15.