SQL Server - Ayuda con cursores

 
Vista:

Ayuda con cursores

Publicado por Juan Rivera (23 intervenciones) el 16/06/2009 00:17:53
Hola a todos, yo de nuevo, el problema que tengo es que he creado un procedimiento almacenado del cual extraigo datos de varias tablas que tienen cientos de miles de registros (de cien miel registros para arriba) y he usado tres cursores para esto porque no he visto otra posibilidad. El primer cursor retorna como mas de 64 mil registros de los cuales cojo el codigo y de ahi hago otro cursor donde retorna como maximo 40 registros cogiendo el codigo del primer cursor y de ahi hago otro cursor donde me retorna como maximo 10 registros cogiendo el codigo del segundo cursor, luego inserto ciertos datos a una tabla temporal y calculo que inserta como decenas de miles de registros y luego los muestra. Hago esto porque no veo otra manera de hacer un reporte que me dejaron. Si hubiera otro metodo que no fueran cursores, me lo podrian indicar, porque esto me demora como mas de media hora y ya no se que hacer.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Ayuda con cursores

Publicado por Restlees (11 intervenciones) el 16/06/2009 05:00:27
Hola.

Puedes poner el codigo que estas usando.????

Creo que mas que todo es optimizar las consultas que usas en los cursores y ver si puedes unificarlos lo mas que puedas.

Como sabes es poco recomendable utilizarlos, como consejo te digo que crees indices a tus tablas, especificamente Nonclustered index. filtra tus consultas con Exists en los Where o And, esto porque usas unos codigos de 2 tablas y podrias mejorar el SQL

Si puedes colocar el codigo usado es mas sencillo y podriamos ver si los optimizamos.

Nos vemos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Ayuda con cursores

Publicado por Juan Rivera (23 intervenciones) el 16/06/2009 18:10:14
Son tres cursores, de repente falta optimizarlos, haber si me dan una mano. El problema es que demora mucho al mostrar (mas de media hora).
El primer cursor bota mas de 62 mil codigos que se tienen que analizar y los demas cursores se filtran por cada codigo del primer cursor (10 registros por cada codigo del primero) y del segundo cursor (de 4 a 11 registros aproximadamente) y lo guardo a un temporal para luego mostrarlos, pero el problema es que demora al guardar al temporal. Lo probe con una tabla normal y es lo mismo, el asunto es que quiero mostrar los registros filtrados.
El tercer cursor compara los montos que tiene un predio por cada propietario, si el primero es mayor que el segundo coge el primero y el segundo y los guarda en dos variables. Si el segundo es menor que el tercero no lo coge y asi sucesivamente sigue comparando.
Como veran son tres bucles y por eso quiero ver si hay otra manera de hacerlo.

alter procedure juan
--@anio1 varchar(4),
--@anio2 varchar(4)
as
declare @aniomodif varchar(4) --Año Modificado
declare @fechmodif datetime --Fecha Modificada
declare @usua varchar(20) --Usuario
declare @anioinic varchar(4) --Año Inicial
declare @nompropiet varchar(200) -- Nombre del Propietario
declare @codper int --Codigo de la Persona
declare @codpred int --Codigo del Predio
declare @montos decimal(10,2) --Monto
declare @a decimal(10,2) --Comparador

/* Cursor de los Propietarios */

declare PropietariosJ Cursor FOR
select distinct p.pers_p_incodper from m_hoja_resu a, m_pers p, m_pred_unic prd where a.pers_p_incodper = p.pers_p_incodper
and prd.hore_p_incodhoj = a.hore_p_incodhoj
and p.pers_p_incodper <> 1
and prd.pred_p_incodpre <> 1
and a.estado = 1
and p.estado = 1
and prd.estado = 1
order by p.pers_p_incodper

open PropietariosJ
fetch next from PropietariosJ INTO @codper
While @@FETCH_STATUS = 0
begin
---------------------------------------------------------------------------------------------
/* Cursor que coge el Predio */

declare PrediosJ Cursor FOR

select distinct prd.pred_p_incodpre from m_hoja_resu a, m_pers p, m_pred_unic prd where a.pers_p_incodper = p.pers_p_incodper and prd.hore_p_incodhoj = a.hore_p_incodhoj and a.estado = 1 and p.estado = 1 and prd.estado = 1 and a.pers_p_incodper = @codper and prd.pred_p_incodpre = @codpred
order by prd.pred_p_incodpre

open PrediosJ
fetch next from PrediosJ INTO @codpred
While @@FETCH_STATUS = 0
Begin
----------------------------------------------------------------------------------
/* Cursor que guarda años y montos iniciales y modificados */
set @a = 0
declare AutoAvaluosJ Cursor FOR

select a.hore_debasnet from m_hoja_resu a, m_pers p, m_pred_unic prd where a.pers_p_incodper = p.pers_p_incodper and prd.hore_p_incodhoj = a.hore_p_incodhoj
and a.estado = 1 and p.estado = 1 and prd.estado = 1 and a.pers_p_incodper = @codper and a.hore_debasnet <> 0
and prd.pred_p_incodpre = @codpred and a.anio_p_chcodano between @anio1 and @anio2
order by p.pers_p_incodper, prd.pred_p_incodpre, anio_p_chcodano

open AutoAvaluosJ
fetch next from AutoAvaluosJ into @montos
While @@FETCH_STATUS = 0
Begin
if @a<>0
begin
if @a>@montos
begin
----Tabla Temporal


declare @Mostrar TABLE (Codigo int, Nombre varchar(200), Anio1 varchar(4), Mon1 decimal(10,2), Anio2 varchar(4), Mon2 decimal(10,2), Usua varchar(20), FechModif varchar(20))

--Nombre del Propietario

select distinct @nompropiet = p.pers_chnomcom from m_pers p, m_pred_unic prd where prd.pers_p_incodper = p.pers_p_incodper and prd.estado = 1 and p.estado = 1 and prd.pers_p_incodper = @codper and prd.pred_p_incodpre = @codpred ----'2825'

----Año Inicial

select @anioinic = a.anio_p_chcodano from m_pers p, m_pred_unic prd, m_hoja_resu a where a.pers_p_incodper = p.pers_p_incodper and prd.hore_p_incodhoj = a.hore_p_incodhoj and a.estado = 1 and prd.estado = 1 and p.estado = 1 and prd.pers_p_incodper = @codper and prd.pred_p_incodpre = @codpred----'2825'
and a.hore_debasnet = @a

--Año Modificado

select @aniomodif = a.anio_p_chcodano from m_pers p, m_pred_unic prd, m_hoja_resu a where a.pers_p_incodper = p.pers_p_incodper and prd.hore_p_incodhoj = a.hore_p_incodhoj and a.estado = 1 and prd.estado = 1 and p.estado = 1 and prd.pers_p_incodper = @codper and prd.pred_p_incodpre = @codpred and a.hore_debasnet = @montos

--Usuario Modificación

select @usua = a.segu_chusulog from m_pers p, m_pred_unic prd, m_hoja_resu a where a.pers_p_incodper = p.pers_p_incodper and prd.hore_p_incodhoj = a.hore_p_incodhoj and a.estado = 1 and prd.estado = 1 and p.estado = 1 and prd.pers_p_incodper = @codper and prd.pred_p_incodpre = @codpred and a.hore_debasnet = @montos

--Fecha Modificación

select @fechmodif = a.segu_chusufec from m_pers p, m_pred_unic prd, m_hoja_resu a where a.pers_p_incodper = p.pers_p_incodper and prd.hore_p_incodhoj = a.hore_p_incodhoj and a.estado = 1 and prd.estado = 1 and p.estado = 1 and prd.pers_p_incodper = @codper and prd.pred_p_incodpre = @codpred and a.hore_debasnet = @montos

/* Aqui lo guardo en la Tabla Temporal */

insert into @Mostrar values (@codpred,@nompropiet, @anioinic,@a,@aniomodif,@montos,@usua,@fechmodif)

end
end

set @a = @montos
fetch next from AutoAvaluosJ into @montos

end

/* Cierro el cursor de los años y montos modificados */

Close AutoAvaluosJ deallocate AutoAvaluosJ

-------------------------------------------------------------------------------

fetch next from PrediosJ into @codpred
end

/* Cierro el cursor de los predios */

Close PrediosJ
deallocate PrediosJ

----------------------------------------------------------------------------------------------------------
fetch next from PropietariosJ INTO @codper
end

/* Cierro el cursor del codigo del propietario */
Close PropietariosJ
deallocate PropietariosJ
--Despues de esto tengo que filtrarlos
select * from @Mostrar

--------------------------------------------------------------------------------------------------------------------------------
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Ayuda con cursores

Publicado por Restlees (11 intervenciones) el 17/06/2009 00:13:14
Saludos.

Lo primero es que debes optimizar tus consultas lo máximo posible. Aca te indico mas o menos la forma correcta de como deben ir. (Estos son los sql de los cursores)

/*1*/
select distinct p.pers_p_incodper
from m_hoja_resu a
INNER JOIN m_pers p
ON a.pers_p_incodper = p.pers_p_incodper
INNER JOIN m_pred_unic prd
ON prd.hore_p_incodhoj = a.hore_p_incodhoj
Where p.pers_p_incodper <> 1
and prd.pred_p_incodpre <> 1
and a.estado = 1
and p.estado = 1
and prd.estado = 1

/*2*/

select distinct prd.pred_p_incodpre
from m_hoja_resu a
INNER JOIN m_pers p
ON a.pers_p_incodper = p.pers_p_incodper
INNER JOIN m_pred_unic prd
ON prd.hore_p_incodhoj = a.hore_p_incodhoj
where a.estado = 1
and p.estado = 1
and prd.estado = 1
and a.pers_p_incodper = @codper
and prd.pred_p_incodpre = @codpred

/*3*/
select a.hore_debasnet
from m_hoja_resu a
INNER JOIN m_pers p
ON a.pers_p_incodper = p.pers_p_incodper
INNER JOIN m_pred_unic prd
On prd.hore_p_incodhoj = a.hore_p_incodhoj
Where a.estado = 1
and p.estado = 1
and prd.estado = 1
and a.pers_p_incodper = @codper
and a.hore_debasnet <> 0
and prd.pred_p_incodpre = @codpred
and a.anio_p_chcodano between @anio1 and @anio2


Trata de no utiilzar el order by, dado que esto te va a demandar mas tiempo al momento de ejecutar un select.

Otro de los puntos es que generes un cursor de la siguiente manera:

Declare
NombreCursor Cursor
Local Fast_Forward For
Select campo1,campo2,campo3
Where X = y
For Read Only

Esta es la mejor manera de crear los cursores.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Ayuda con cursores

Publicado por Juan Rivera (23 intervenciones) el 19/06/2009 18:41:00
Gracias por tu respuesta Restlees, pero lo que hice fue que de los tres cursores juntarlo todo en uno solo y ahi demora casi 3 minutos, pero igual creo que eso era lo mejor. Graciass.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Isaias
Val: 3.250
Oro
Ha mantenido su posición en SQL Server (en relación al último mes)
Gráfica de SQL Server

RE:Ayuda con cursores

Publicado por Isaias (4558 intervenciones) el 20/06/2009 00:07:34
Juan

¿Sabias que los cursores se crean en MEMORIA RAM?

El 99.99% de las cosas que se hacen con cursores, se pueden hacer con T-SQL normal.

Preferentemente, olvidate que existen los cursores, mejor dinos, que deseas hacer ......
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar