Maxi: Cursores en SQL Server, por que no son tan malos :P

25/11/2004 - 17:40 por K | Informe spam
Saludos Maxi

Yo he tenido esa discusión, pero en realidad no solo de cursores, sino de la
mayor parte de la plataforma de desarrollo de Microsoft, ja ja ja, muchas
personas piensan que lo mas basico es lo mejor, y no lo es en el 100% de los
casos, como VS6 vs VS.Net, pero, acerca de SQL principalmente las
discusiones han sido acerca de tablas temporales VS cursores para hacer
scroll en un resultSet, de cualquier forma, aquí va por que considero una
ayuda benigna los cursores, precisamente ayer tuve un detalle acerca de eso,
te muestro el query que estuve trabajando

SELECT
F1.ABAN8 AS ClientID,
CASE
WHEN MIN(PS.FechaActivacion) IS Null THEN 0
ELSE 1
END AS ESelling,
MIN(PS.FechaActivacion) AS ESellingDate,
CASE
WHEN Wap.wapServiceDate IS Null THEN 0
ELSE 1
END AS Wap,
Wap.wapServiceDate AS WapDate,
CASE
WHEN x24Hrs.x24HrsServiceDate IS Null THEN 0
ELSE 1
END AS x24Hrs,
x24Hrs.x24HrsServiceDate AS x24HrsDate,
CASE
WHEN MIN(UGF.StartDate) IS Null THEN 0
ELSE 1
END AS CemPlus,
MIN(UGF.StartDate) AS CemPlusDate,
CASE
WHEN MIN(TCC.RegistrationDate) Is Null THEN 0
ELSE 1
END AS CCases,
MIN(TCC.RegistrationDate) AS CCasesDate,
CASE
WHEN Eficem.EficemDate IS NULL THEN 0 -- Aqui no utilizamos MIN por que
siempre me trae un solo registro
ELSE 1
END AS Eficem,
Eficem.EficemDate AS EficemDate

FROM
F0101 F1
LEFT JOIN EsEsp300.dbo.FProspectos AS PS ON F1.ABAN8 = PS.Cliente --AND
PS.FechaActivacion Is Not Null
LEFT JOIN vw_UsersGF AS UGF ON F1.ABAN8 = UGF.JDECode
LEFT JOIN tCASCases TCC ON F1.ABAN8 = TCC.BranchID
LEFT JOIN (
SELECT
UGF.JDECode AS JDECode,
A.StartDate AS EficemDate
FROM
cpEsp300.dbo.Agreement A
INNER JOIN vw_UsersGF UGF ON A.IDUser = UGF.IDUser
) AS Eficem ON F1.ABAN8 = Eficem.JDECode
LEFT JOIN (
SELECT
T1.SDAN8 AS SDAN8,
CASE WHEN T2.Counter2 IS NULL THEN T1.Counter
ELSE T2.Counter2
END AS x24HrsServiceDate
FROM
(SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 = 3
AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T1 FULL JOIN
(SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2 WHERE
SDUPC1 = 3 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T2 ON T1.SDAN8 T2.SDAN82
) AS x24Hrs ON x24Hrs.SDAN8 = F1.ABAN8
LEFT JOIN (
SELECT
T3.SDAN8 AS SDAN8,
CASE WHEN T4.Counter2 IS NULL THEN T3.Counter
ELSE T4.Counter2
END AS WapServiceDate
FROM
(SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 = 2
AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T3 FULL JOIN
(SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2 WHERE
SDUPC1 = 2 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T4 ON T3.SDAN8 T4.SDAN82
) AS Wap ON F1.ABAN8 = Wap.SDAN8
GROUP BY
F1.ABAN8, Wap.wapServiceDate, x24Hrs.x24HrsServiceDate, Eficem.JDECode,
Eficem.EficemDate
HAVING
MIN(PS.FechaActivacion) Is Not Null OR
MIN(Wap.wapServiceDate) Is Not Null OR
MIN(x24Hrs.x24HrsServiceDate) Is Not Null OR
MIN(UGF.StartDate) Is Not Null OR
MIN(TCC.RegistrationDate) Is Not Null

Bueno, como background, la tabla que saca los valores, con DISTINCT (que es
algo asi como la "llave", es con lo que sabemos que registros afectar),
produce 220000+ regs como Result Set, ahora, eso no es problema y SQL los
recupera en menos de 2 secs, el problema viene por que, en la tabla F42119,
consiste de mas de 3 000 000+ regs, filtrandola con la llave, la consula es
instantánea (foreignKey = 'value'), pero en el SELECT no puedo mandarle a un
SELECT anidado el valor explícito de la llave, eso lo tuve que emular con el
JOIN externo (AS Wap ON F1.ABAN8 = Wap.SDAN8), además, las tablas F4211 y
F42119 son identicas, solo que una contiene registros históricos (La de los
3M+) y no puedo utilizar UNION, por que el UNION me producía muchisimos mas
registros y hacía mas pesado el JOIN del nivel superior, y al no poder
enviarle sino atravez del JOIN la llave contra que filtrarlo para cada
registro en particula, me tardaba aún mas.

Como sea, con varias optimizaciones al nivel donde los SELECT metían los
filtrajes, lo mas que pude reducir el tiempo fue a no menos de 5 mins, via
un solo select, mientras que con el cursor corría en mas o menos 4 mins, no
es mucha diferencia, pero teoricamente, el tiempo crecerá exponencialmente
mas para el SELECT que para el CURSOR, por que el cursor manda un valor
especifico a un SP que tiene las colsultas necesarias para generar los
resultados que necesito

En esta ocasión, al menos en las pruebas que hice, el Cursor desempeño de
mejor forma, y el SELECT me afectaba cuando quería correr otro query a
alguna de las tablas, me marcaba timeout, con el Cursor corriendo no, igual
se alentaba el Query, pero respondía, quizá esto ultimo fue coincidencia,
pero fue en mas de una ocasión. E incluso, una de las veces que lo corrí
solo, el mismo parecía como bloquearse en los ultimos registros, y tardó mas
de 20 Min.

Y pues nada mas como respuesta rapida también al respecto, cuando entablo
una discusión sobre cursores, hay cosas que desafortunadamente de otra forma
no puedes realizar, suponiendo por ejemplo, que tuvieras un sistema que
trabajaras con probabilidades, y necesitaras generar números aleatorios para
proyecciones, utilizar RAND en un SELECT pe. SELECT RAND() AS Tendencia,
Field AS Factor FROM TablaHistorico, te va a utilizar el mismo número
aleatorio atravez de todo el Result Set, lo cual, pues sería incorrecto.

Quizá tu nunca has tenido necesidad de utilizarlos en base a los proyectos
que has estado, pero yo sigo pensando que, como la mayoría de las
tecnologías un poco mas complejonas de MS, bien usados, no son un enemigo. Y
decir que su uso es patético, me parece... cierto, pero no siempre.

De cualquier forma, sigo trabajando en ese query, por que me pareció
interesante el hecho de tratar de reducir el tiempo de consulta moviendo de
niveles el filtraje (incluso sacandolo del contexto inicial ^_^) te aviso si
pude hacer que el SELECT jalara aún mas rápido. Suerte

K' Ragnarok





"MAXI" <maxi_da@infovia.com.ar.sacame> wrote in message
news:OLKkXaP0EHA.2804@TK2MSFTNGP15.phx.gbl...

Hola, podrias ampliar un poco en que te basas que los cursores ayudan? yo
considero que son muy malos para tareas de produccion y que se usan porque
es mas facil :(

Te cuento mas, hace unos dias tuve una linda discusion con arquitectos


.net

sobre este tema y demostre que el uso de cursores es patetico para


cualquier

cosa




Maxi

Buenos Aires - Argentina
Desarrollador .NET 3 Estrellas
Microsoft User Group (MUG)
Mail: Maxi_accotto[arroba]speedy.com.ar

Msn Messenger: Maxi_adrogue@msn.com

"K'" <soki.gakiya@adepsa.com.mx> escribió en el mensaje
news:O0xmLPP0EHA.2540@TK2MSFTNGP09.phx.gbl...
> De hecho, si revisas los resultados de tu cursor, hace un fetch linea


por

> linea, como si hicieras un SELECT por renglón
>
> Si creas el SP y lo ejecutas desde QA, debe traerte exactamente el mismo
> resultado (una especie de query multiple), al parecer al no descargar


los

> valores en variables, el CURSOR lo toma como consultas completas
>
> Y supongo que si eso lo estás capturando con ADO, por eso solo te


regresa

> un
> resultset
>
> En realidad no entendí bien cual es tu tirada con ese CURSOR, me parece
> que
> puedes lograr la funcionalidad necesaria sin uso del mismo, los CURSORES
> no
> son malos usados correctamente, te ayudar a agilizar procesos, pero mal
> usados, si representan un riesgo enorme, especialmente en performance,


así

> que mejor dejalos para cuando todo lo demás atenta de forma mas
> comprometedora en tu sistema.
>
> Si nos especificas que necesitas hacer, será mas facil apuntarte en la


dir

> para solucionar tu problema
>
> K'
>
> "Paulino Padial" <paulifoc@telefonica.net> wrote in message
> news:%23X$b4aO0EHA.2688@TK2MSFTNGP09.phx.gbl...
>> Una pregunta, ¿ Te devuelve solo la ultima fila ? , puede ser que


vayan

> por
>> ahi los tiros ;-)
>>
>>
>> "fabicabrera@yahoo.com" <anonymous@discussions.microsoft.com> escribió


en

> el
>> mensaje news:873301c4d0e3$d25fbde0$a601280a@phx.gbl...
>> > Saludos Grupo!
>> >
>> > Necesito crar una consulta como la que sigue
>> > ***********
>> > Use Pubs
>> > Go
>> > DECLARE authors_cursor CURSOR
>> > FOR SELECT * FROM authors
>> > OPEN authors_cursor
>> >
>> > FETCH NEXT FROM authors_cursor
>> > WHILE @@FETCH_STATUS = 0
>> > BEGIN
>> > FETCH NEXT FROM authors_cursor
>> > END
>> > CLOSE authors_cursor
>> > DEALLOCATE authors_cursor
>> > ****
>> >
>> > Cuando lo ejecuto en el analizador de consultas de SQL
>> > funciona perfectamente, pero cuando lo guardo en un
>> > procedimieto almacenado y lo llamo desde mi aplicacion me
>> > retorna solo la primera fila...
>> >
>> > Si alguien puede ayudarme, gracias de Antemano
>> >
>> > Fabi
>>
>>
>
>


Preguntas similare

Leer las respuestas

#1 Maxi
25/11/2004 - 18:28 | Informe spam
Hola, mira deberia tener las tablas para poder analizar mejor el caso!! pero
me parece que hay algunas cosas que no me cierran ;)

Si la tabla tiene 3M de registros los necesitas todos?

Ademas habria que ver tema de indices y otras yerbas, pero te aseguro que un
select tarda menos que un cursor en el 99% de los casos. Eso si, si haces un
tableScan (que es seguro lo que te esta pasando con la de 3M) va a demorar
un lindo ratito ;)

Tambien puedes probar de cambiar el nivel de aislamiento en la query y
probar


Salu2
Maxi


"K'" escribió en el mensaje
news:
Saludos Maxi

Yo he tenido esa discusión, pero en realidad no solo de cursores, sino de
la
mayor parte de la plataforma de desarrollo de Microsoft, ja ja ja, muchas
personas piensan que lo mas basico es lo mejor, y no lo es en el 100% de
los
casos, como VS6 vs VS.Net, pero, acerca de SQL principalmente las
discusiones han sido acerca de tablas temporales VS cursores para hacer
scroll en un resultSet, de cualquier forma, aquí va por que considero una
ayuda benigna los cursores, precisamente ayer tuve un detalle acerca de
eso,
te muestro el query que estuve trabajando

SELECT
F1.ABAN8 AS ClientID,
CASE
WHEN MIN(PS.FechaActivacion) IS Null THEN 0
ELSE 1
END AS ESelling,
MIN(PS.FechaActivacion) AS ESellingDate,
CASE
WHEN Wap.wapServiceDate IS Null THEN 0
ELSE 1
END AS Wap,
Wap.wapServiceDate AS WapDate,
CASE
WHEN x24Hrs.x24HrsServiceDate IS Null THEN 0
ELSE 1
END AS x24Hrs,
x24Hrs.x24HrsServiceDate AS x24HrsDate,
CASE
WHEN MIN(UGF.StartDate) IS Null THEN 0
ELSE 1
END AS CemPlus,
MIN(UGF.StartDate) AS CemPlusDate,
CASE
WHEN MIN(TCC.RegistrationDate) Is Null THEN 0
ELSE 1
END AS CCases,
MIN(TCC.RegistrationDate) AS CCasesDate,
CASE
WHEN Eficem.EficemDate IS NULL THEN 0 -- Aqui no utilizamos MIN por
que
siempre me trae un solo registro
ELSE 1
END AS Eficem,
Eficem.EficemDate AS EficemDate

FROM
F0101 F1
LEFT JOIN EsEsp300.dbo.FProspectos AS PS ON F1.ABAN8 = PS.Cliente --AND
PS.FechaActivacion Is Not Null
LEFT JOIN vw_UsersGF AS UGF ON F1.ABAN8 = UGF.JDECode
LEFT JOIN tCASCases TCC ON F1.ABAN8 = TCC.BranchID
LEFT JOIN (
SELECT
UGF.JDECode AS JDECode,
A.StartDate AS EficemDate
FROM
cpEsp300.dbo.Agreement A
INNER JOIN vw_UsersGF UGF ON A.IDUser = UGF.IDUser
) AS Eficem ON F1.ABAN8 = Eficem.JDECode
LEFT JOIN (
SELECT
T1.SDAN8 AS SDAN8,
CASE WHEN T2.Counter2 IS NULL THEN T1.Counter
ELSE T2.Counter2
END AS x24HrsServiceDate
FROM
(SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 = 3
AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T1 FULL JOIN
(SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2 WHERE
SDUPC1 = 3 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T2 ON T1.SDAN8 > T2.SDAN82
) AS x24Hrs ON x24Hrs.SDAN8 = F1.ABAN8
LEFT JOIN (
SELECT
T3.SDAN8 AS SDAN8,
CASE WHEN T4.Counter2 IS NULL THEN T3.Counter
ELSE T4.Counter2
END AS WapServiceDate
FROM
(SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 = 2
AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T3 FULL JOIN
(SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2 WHERE
SDUPC1 = 2 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T4 ON T3.SDAN8 > T4.SDAN82
) AS Wap ON F1.ABAN8 = Wap.SDAN8
GROUP BY
F1.ABAN8, Wap.wapServiceDate, x24Hrs.x24HrsServiceDate, Eficem.JDECode,
Eficem.EficemDate
HAVING
MIN(PS.FechaActivacion) Is Not Null OR
MIN(Wap.wapServiceDate) Is Not Null OR
MIN(x24Hrs.x24HrsServiceDate) Is Not Null OR
MIN(UGF.StartDate) Is Not Null OR
MIN(TCC.RegistrationDate) Is Not Null

Bueno, como background, la tabla que saca los valores, con DISTINCT (que
es
algo asi como la "llave", es con lo que sabemos que registros afectar),
produce 220000+ regs como Result Set, ahora, eso no es problema y SQL los
recupera en menos de 2 secs, el problema viene por que, en la tabla
F42119,
consiste de mas de 3 000 000+ regs, filtrandola con la llave, la consula
es
instantánea (foreignKey = 'value'), pero en el SELECT no puedo mandarle a
un
SELECT anidado el valor explícito de la llave, eso lo tuve que emular con
el
JOIN externo (AS Wap ON F1.ABAN8 = Wap.SDAN8), además, las tablas F4211 y
F42119 son identicas, solo que una contiene registros históricos (La de
los
3M+) y no puedo utilizar UNION, por que el UNION me producía muchisimos
mas
registros y hacía mas pesado el JOIN del nivel superior, y al no poder
enviarle sino atravez del JOIN la llave contra que filtrarlo para cada
registro en particula, me tardaba aún mas.

Como sea, con varias optimizaciones al nivel donde los SELECT metían los
filtrajes, lo mas que pude reducir el tiempo fue a no menos de 5 mins, via
un solo select, mientras que con el cursor corría en mas o menos 4 mins,
no
es mucha diferencia, pero teoricamente, el tiempo crecerá exponencialmente
mas para el SELECT que para el CURSOR, por que el cursor manda un valor
especifico a un SP que tiene las colsultas necesarias para generar los
resultados que necesito

En esta ocasión, al menos en las pruebas que hice, el Cursor desempeño de
mejor forma, y el SELECT me afectaba cuando quería correr otro query a
alguna de las tablas, me marcaba timeout, con el Cursor corriendo no,
igual
se alentaba el Query, pero respondía, quizá esto ultimo fue coincidencia,
pero fue en mas de una ocasión. E incluso, una de las veces que lo corrí
solo, el mismo parecía como bloquearse en los ultimos registros, y tardó
mas
de 20 Min.

Y pues nada mas como respuesta rapida también al respecto, cuando entablo
una discusión sobre cursores, hay cosas que desafortunadamente de otra
forma
no puedes realizar, suponiendo por ejemplo, que tuvieras un sistema que
trabajaras con probabilidades, y necesitaras generar números aleatorios
para
proyecciones, utilizar RAND en un SELECT pe. SELECT RAND() AS Tendencia,
Field AS Factor FROM TablaHistorico, te va a utilizar el mismo número
aleatorio atravez de todo el Result Set, lo cual, pues sería incorrecto.

Quizá tu nunca has tenido necesidad de utilizarlos en base a los proyectos
que has estado, pero yo sigo pensando que, como la mayoría de las
tecnologías un poco mas complejonas de MS, bien usados, no son un enemigo.
Y
decir que su uso es patético, me parece... cierto, pero no siempre.

De cualquier forma, sigo trabajando en ese query, por que me pareció
interesante el hecho de tratar de reducir el tiempo de consulta moviendo
de
niveles el filtraje (incluso sacandolo del contexto inicial ^_^) te aviso
si
pude hacer que el SELECT jalara aún mas rápido. Suerte

K' Ragnarok





"MAXI" wrote in message
news:
Hola, podrias ampliar un poco en que te basas que los cursores ayudan? yo
considero que son muy malos para tareas de produccion y que se usan
porque
es mas facil :(

Te cuento mas, hace unos dias tuve una linda discusion con arquitectos


.net
sobre este tema y demostre que el uso de cursores es patetico para


cualquier
cosa




Maxi

Buenos Aires - Argentina
Desarrollador .NET 3 Estrellas
Microsoft User Group (MUG)
Mail: Maxi_accotto[arroba]speedy.com.ar

Msn Messenger:

"K'" escribió en el mensaje
news:
> De hecho, si revisas los resultados de tu cursor, hace un fetch linea


por
> linea, como si hicieras un SELECT por renglón
>
> Si creas el SP y lo ejecutas desde QA, debe traerte exactamente el
> mismo
> resultado (una especie de query multiple), al parecer al no descargar


los
> valores en variables, el CURSOR lo toma como consultas completas
>
> Y supongo que si eso lo estás capturando con ADO, por eso solo te


regresa
> un
> resultset
>
> En realidad no entendí bien cual es tu tirada con ese CURSOR, me parece
> que
> puedes lograr la funcionalidad necesaria sin uso del mismo, los
> CURSORES
> no
> son malos usados correctamente, te ayudar a agilizar procesos, pero mal
> usados, si representan un riesgo enorme, especialmente en performance,


así
> que mejor dejalos para cuando todo lo demás atenta de forma mas
> comprometedora en tu sistema.
>
> Si nos especificas que necesitas hacer, será mas facil apuntarte en la


dir
> para solucionar tu problema
>
> K'
>
> "Paulino Padial" wrote in message
> news:%23X$
>> Una pregunta, ¿ Te devuelve solo la ultima fila ? , puede ser que


vayan
> por
>> ahi los tiros ;-)
>>
>>
>> "" escribió


en
> el
>> mensaje news:873301c4d0e3$d25fbde0$
>> > Saludos Grupo!
>> >
>> > Necesito crar una consulta como la que sigue
>> > ***********
>> > Use Pubs
>> > Go
>> > DECLARE authors_cursor CURSOR
>> > FOR SELECT * FROM authors
>> > OPEN authors_cursor
>> >
>> > FETCH NEXT FROM authors_cursor
>> > WHILE @@FETCH_STATUS = 0
>> > BEGIN
>> > FETCH NEXT FROM authors_cursor
>> > END
>> > CLOSE authors_cursor
>> > DEALLOCATE authors_cursor
>> > ****
>> >
>> > Cuando lo ejecuto en el analizador de consultas de SQL
>> > funciona perfectamente, pero cuando lo guardo en un
>> > procedimieto almacenado y lo llamo desde mi aplicacion me
>> > retorna solo la primera fila...
>> >
>> > Si alguien puede ayudarme, gracias de Antemano
>> >
>> > Fabi
>>
>>
>
>






Respuesta Responder a este mensaje
#2 K
25/11/2004 - 19:04 | Informe spam
En realidad la tabla no está normalizada, y no fui yo quien la diseñó, de
forma que no conozco bien como va a quedar al final, mi idea es que ya
normalizada va a ser aún mas rápido y si, son muchisimo mas rapidos, estoy
de acuerdo, mi otra idea de hecho fue hacer, mediante funciones de agregado
(que es realmente lo que necesito en todas las tablas (valores mínimos)) un
espejo menor (MUCHO menor) de las tablas grandes, pero como que era mas
tardado aún no sé por que, no puedo utilizar temporales, de forma que hice
una var tipo tabla, y te digo, fue tardado

Acerca de lo del nivel de aislamiento, a que te refieres? comprendo mas o
menos, pero no me queda muy claro, de forma que no sé que responderte sin
arriegarme a meter la pata :P

K'

"Maxi" wrote in message
news:%
Hola, mira deberia tener las tablas para poder analizar mejor el caso!!


pero
me parece que hay algunas cosas que no me cierran ;)

Si la tabla tiene 3M de registros los necesitas todos?

Ademas habria que ver tema de indices y otras yerbas, pero te aseguro que


un
select tarda menos que un cursor en el 99% de los casos. Eso si, si haces


un
tableScan (que es seguro lo que te esta pasando con la de 3M) va a demorar
un lindo ratito ;)

Tambien puedes probar de cambiar el nivel de aislamiento en la query y
probar


Salu2
Maxi


"K'" escribió en el mensaje
news:
> Saludos Maxi
>
> Yo he tenido esa discusión, pero en realidad no solo de cursores, sino


de
> la
> mayor parte de la plataforma de desarrollo de Microsoft, ja ja ja,


muchas
> personas piensan que lo mas basico es lo mejor, y no lo es en el 100% de
> los
> casos, como VS6 vs VS.Net, pero, acerca de SQL principalmente las
> discusiones han sido acerca de tablas temporales VS cursores para hacer
> scroll en un resultSet, de cualquier forma, aquí va por que considero


una
> ayuda benigna los cursores, precisamente ayer tuve un detalle acerca de
> eso,
> te muestro el query que estuve trabajando
>
> SELECT
> F1.ABAN8 AS ClientID,
> CASE
> WHEN MIN(PS.FechaActivacion) IS Null THEN 0
> ELSE 1
> END AS ESelling,
> MIN(PS.FechaActivacion) AS ESellingDate,
> CASE
> WHEN Wap.wapServiceDate IS Null THEN 0
> ELSE 1
> END AS Wap,
> Wap.wapServiceDate AS WapDate,
> CASE
> WHEN x24Hrs.x24HrsServiceDate IS Null THEN 0
> ELSE 1
> END AS x24Hrs,
> x24Hrs.x24HrsServiceDate AS x24HrsDate,
> CASE
> WHEN MIN(UGF.StartDate) IS Null THEN 0
> ELSE 1
> END AS CemPlus,
> MIN(UGF.StartDate) AS CemPlusDate,
> CASE
> WHEN MIN(TCC.RegistrationDate) Is Null THEN 0
> ELSE 1
> END AS CCases,
> MIN(TCC.RegistrationDate) AS CCasesDate,
> CASE
> WHEN Eficem.EficemDate IS NULL THEN 0 -- Aqui no utilizamos MIN por
> que
> siempre me trae un solo registro
> ELSE 1
> END AS Eficem,
> Eficem.EficemDate AS EficemDate
>
> FROM
> F0101 F1
> LEFT JOIN EsEsp300.dbo.FProspectos AS PS ON F1.ABAN8 PS.Cliente --AND
> PS.FechaActivacion Is Not Null
> LEFT JOIN vw_UsersGF AS UGF ON F1.ABAN8 = UGF.JDECode
> LEFT JOIN tCASCases TCC ON F1.ABAN8 = TCC.BranchID
> LEFT JOIN (
> SELECT
> UGF.JDECode AS JDECode,
> A.StartDate AS EficemDate
> FROM
> cpEsp300.dbo.Agreement A
> INNER JOIN vw_UsersGF UGF ON A.IDUser = UGF.IDUser
> ) AS Eficem ON F1.ABAN8 = Eficem.JDECode
> LEFT JOIN (
> SELECT
> T1.SDAN8 AS SDAN8,
> CASE WHEN T2.Counter2 IS NULL THEN T1.Counter
> ELSE T2.Counter2
> END AS x24HrsServiceDate
> FROM
> (SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 3
> AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T1 FULL JOIN
> (SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2


WHERE
> SDUPC1 = 3 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T2 ON T1.SDAN8 > > T2.SDAN82
> ) AS x24Hrs ON x24Hrs.SDAN8 = F1.ABAN8
> LEFT JOIN (
> SELECT
> T3.SDAN8 AS SDAN8,
> CASE WHEN T4.Counter2 IS NULL THEN T3.Counter
> ELSE T4.Counter2
> END AS WapServiceDate
> FROM
> (SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 2
> AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T3 FULL JOIN
> (SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2


WHERE
> SDUPC1 = 2 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T4 ON T3.SDAN8 > > T4.SDAN82
> ) AS Wap ON F1.ABAN8 = Wap.SDAN8
> GROUP BY
> F1.ABAN8, Wap.wapServiceDate, x24Hrs.x24HrsServiceDate,


Eficem.JDECode,
> Eficem.EficemDate
> HAVING
> MIN(PS.FechaActivacion) Is Not Null OR
> MIN(Wap.wapServiceDate) Is Not Null OR
> MIN(x24Hrs.x24HrsServiceDate) Is Not Null OR
> MIN(UGF.StartDate) Is Not Null OR
> MIN(TCC.RegistrationDate) Is Not Null
>
> Bueno, como background, la tabla que saca los valores, con DISTINCT (que
> es
> algo asi como la "llave", es con lo que sabemos que registros afectar),
> produce 220000+ regs como Result Set, ahora, eso no es problema y SQL


los
> recupera en menos de 2 secs, el problema viene por que, en la tabla
> F42119,
> consiste de mas de 3 000 000+ regs, filtrandola con la llave, la consula
> es
> instantánea (foreignKey = 'value'), pero en el SELECT no puedo mandarle


a
> un
> SELECT anidado el valor explícito de la llave, eso lo tuve que emular


con
> el
> JOIN externo (AS Wap ON F1.ABAN8 = Wap.SDAN8), además, las tablas F4211


y
> F42119 son identicas, solo que una contiene registros históricos (La de
> los
> 3M+) y no puedo utilizar UNION, por que el UNION me producía muchisimos
> mas
> registros y hacía mas pesado el JOIN del nivel superior, y al no poder
> enviarle sino atravez del JOIN la llave contra que filtrarlo para cada
> registro en particula, me tardaba aún mas.
>
> Como sea, con varias optimizaciones al nivel donde los SELECT metían los
> filtrajes, lo mas que pude reducir el tiempo fue a no menos de 5 mins,


via
> un solo select, mientras que con el cursor corría en mas o menos 4 mins,
> no
> es mucha diferencia, pero teoricamente, el tiempo crecerá


exponencialmente
> mas para el SELECT que para el CURSOR, por que el cursor manda un valor
> especifico a un SP que tiene las colsultas necesarias para generar los
> resultados que necesito
>
> En esta ocasión, al menos en las pruebas que hice, el Cursor desempeño


de
> mejor forma, y el SELECT me afectaba cuando quería correr otro query a
> alguna de las tablas, me marcaba timeout, con el Cursor corriendo no,
> igual
> se alentaba el Query, pero respondía, quizá esto ultimo fue


coincidencia,
> pero fue en mas de una ocasión. E incluso, una de las veces que lo corrí
> solo, el mismo parecía como bloquearse en los ultimos registros, y tardó
> mas
> de 20 Min.
>
> Y pues nada mas como respuesta rapida también al respecto, cuando


entablo
> una discusión sobre cursores, hay cosas que desafortunadamente de otra
> forma
> no puedes realizar, suponiendo por ejemplo, que tuvieras un sistema que
> trabajaras con probabilidades, y necesitaras generar números aleatorios
> para
> proyecciones, utilizar RAND en un SELECT pe. SELECT RAND() AS Tendencia,
> Field AS Factor FROM TablaHistorico, te va a utilizar el mismo número
> aleatorio atravez de todo el Result Set, lo cual, pues sería incorrecto.
>
> Quizá tu nunca has tenido necesidad de utilizarlos en base a los


proyectos
> que has estado, pero yo sigo pensando que, como la mayoría de las
> tecnologías un poco mas complejonas de MS, bien usados, no son un


enemigo.
> Y
> decir que su uso es patético, me parece... cierto, pero no siempre.
>
> De cualquier forma, sigo trabajando en ese query, por que me pareció
> interesante el hecho de tratar de reducir el tiempo de consulta moviendo
> de
> niveles el filtraje (incluso sacandolo del contexto inicial ^_^) te


aviso
> si
> pude hacer que el SELECT jalara aún mas rápido. Suerte
>
> K' Ragnarok
>
>
>
>
>
> "MAXI" wrote in message
> news:
>> Hola, podrias ampliar un poco en que te basas que los cursores ayudan?


yo
>> considero que son muy malos para tareas de produccion y que se usan
>> porque
>> es mas facil :(
>>
>> Te cuento mas, hace unos dias tuve una linda discusion con arquitectos
> .net
>> sobre este tema y demostre que el uso de cursores es patetico para
> cualquier
>> cosa
>>
>>
>>
>>
>> Maxi
>>
>> Buenos Aires - Argentina
>> Desarrollador .NET 3 Estrellas
>> Microsoft User Group (MUG)
>> Mail: Maxi_accotto[arroba]speedy.com.ar
>>
>> Msn Messenger:
>>
>> "K'" escribió en el mensaje
>> news:
>> > De hecho, si revisas los resultados de tu cursor, hace un fetch linea
> por
>> > linea, como si hicieras un SELECT por renglón
>> >
>> > Si creas el SP y lo ejecutas desde QA, debe traerte exactamente el
>> > mismo
>> > resultado (una especie de query multiple), al parecer al no descargar
> los
>> > valores en variables, el CURSOR lo toma como consultas completas
>> >
>> > Y supongo que si eso lo estás capturando con ADO, por eso solo te
> regresa
>> > un
>> > resultset
>> >
>> > En realidad no entendí bien cual es tu tirada con ese CURSOR, me


parece
>> > que
>> > puedes lograr la funcionalidad necesaria sin uso del mismo, los
>> > CURSORES
>> > no
>> > son malos usados correctamente, te ayudar a agilizar procesos, pero


mal
>> > usados, si representan un riesgo enorme, especialmente en


performance,
> así
>> > que mejor dejalos para cuando todo lo demás atenta de forma mas
>> > comprometedora en tu sistema.
>> >
>> > Si nos especificas que necesitas hacer, será mas facil apuntarte en


la
> dir
>> > para solucionar tu problema
>> >
>> > K'
>> >
>> > "Paulino Padial" wrote in message
>> > news:%23X$
>> >> Una pregunta, ¿ Te devuelve solo la ultima fila ? , puede ser que
> vayan
>> > por
>> >> ahi los tiros ;-)
>> >>
>> >>
>> >> ""


escribió
> en
>> > el
>> >> mensaje news:873301c4d0e3$d25fbde0$
>> >> > Saludos Grupo!
>> >> >
>> >> > Necesito crar una consulta como la que sigue
>> >> > ***********
>> >> > Use Pubs
>> >> > Go
>> >> > DECLARE authors_cursor CURSOR
>> >> > FOR SELECT * FROM authors
>> >> > OPEN authors_cursor
>> >> >
>> >> > FETCH NEXT FROM authors_cursor
>> >> > WHILE @@FETCH_STATUS = 0
>> >> > BEGIN
>> >> > FETCH NEXT FROM authors_cursor
>> >> > END
>> >> > CLOSE authors_cursor
>> >> > DEALLOCATE authors_cursor
>> >> > ****
>> >> >
>> >> > Cuando lo ejecuto en el analizador de consultas de SQL
>> >> > funciona perfectamente, pero cuando lo guardo en un
>> >> > procedimieto almacenado y lo llamo desde mi aplicacion me
>> >> > retorna solo la primera fila...
>> >> >
>> >> > Si alguien puede ayudarme, gracias de Antemano
>> >> >
>> >> > Fabi
>> >>
>> >>
>> >
>> >
>>
>>
>
>


Respuesta Responder a este mensaje
#3 Maxi
25/11/2004 - 19:13 | Informe spam
Hola, bueno como te dije antes!! habria que ver varias cosas en esa
megaconsulta!! quizas los indices no sean los correctos por ej y se esten
usando cluster scan (si nos pasas el plan de ejecucion seria muy bueno)

Cuando hablo del aislamiento me refiero a esto:

SET TRANSACTION ISOLATION LEVEL

Quizas poniendo que no bloquee tarde mucho menos!! claro tiene sus riegos
pero... habria que analizar la cosa mas en profundidad para poder dar una
solucion acertada. De algo estoy seguro, con un SELECT siempre sera mejor,
una de las razones es la velocidad, otra los bloqueos que generan los
cursores y una tercera es la escalabilidad!!


Salu2
Maxi


"K'" escribió en el mensaje
news:
En realidad la tabla no está normalizada, y no fui yo quien la diseñó, de
forma que no conozco bien como va a quedar al final, mi idea es que ya
normalizada va a ser aún mas rápido y si, son muchisimo mas rapidos, estoy
de acuerdo, mi otra idea de hecho fue hacer, mediante funciones de
agregado
(que es realmente lo que necesito en todas las tablas (valores mínimos))
un
espejo menor (MUCHO menor) de las tablas grandes, pero como que era mas
tardado aún no sé por que, no puedo utilizar temporales, de forma que hice
una var tipo tabla, y te digo, fue tardado

Acerca de lo del nivel de aislamiento, a que te refieres? comprendo mas o
menos, pero no me queda muy claro, de forma que no sé que responderte sin
arriegarme a meter la pata :P

K'

"Maxi" wrote in message
news:%
Hola, mira deberia tener las tablas para poder analizar mejor el caso!!


pero
me parece que hay algunas cosas que no me cierran ;)

Si la tabla tiene 3M de registros los necesitas todos?

Ademas habria que ver tema de indices y otras yerbas, pero te aseguro que


un
select tarda menos que un cursor en el 99% de los casos. Eso si, si haces


un
tableScan (que es seguro lo que te esta pasando con la de 3M) va a
demorar
un lindo ratito ;)

Tambien puedes probar de cambiar el nivel de aislamiento en la query y
probar


Salu2
Maxi


"K'" escribió en el mensaje
news:
> Saludos Maxi
>
> Yo he tenido esa discusión, pero en realidad no solo de cursores, sino


de
> la
> mayor parte de la plataforma de desarrollo de Microsoft, ja ja ja,


muchas
> personas piensan que lo mas basico es lo mejor, y no lo es en el 100%
> de
> los
> casos, como VS6 vs VS.Net, pero, acerca de SQL principalmente las
> discusiones han sido acerca de tablas temporales VS cursores para hacer
> scroll en un resultSet, de cualquier forma, aquí va por que considero


una
> ayuda benigna los cursores, precisamente ayer tuve un detalle acerca de
> eso,
> te muestro el query que estuve trabajando
>
> SELECT
> F1.ABAN8 AS ClientID,
> CASE
> WHEN MIN(PS.FechaActivacion) IS Null THEN 0
> ELSE 1
> END AS ESelling,
> MIN(PS.FechaActivacion) AS ESellingDate,
> CASE
> WHEN Wap.wapServiceDate IS Null THEN 0
> ELSE 1
> END AS Wap,
> Wap.wapServiceDate AS WapDate,
> CASE
> WHEN x24Hrs.x24HrsServiceDate IS Null THEN 0
> ELSE 1
> END AS x24Hrs,
> x24Hrs.x24HrsServiceDate AS x24HrsDate,
> CASE
> WHEN MIN(UGF.StartDate) IS Null THEN 0
> ELSE 1
> END AS CemPlus,
> MIN(UGF.StartDate) AS CemPlusDate,
> CASE
> WHEN MIN(TCC.RegistrationDate) Is Null THEN 0
> ELSE 1
> END AS CCases,
> MIN(TCC.RegistrationDate) AS CCasesDate,
> CASE
> WHEN Eficem.EficemDate IS NULL THEN 0 -- Aqui no utilizamos MIN por
> que
> siempre me trae un solo registro
> ELSE 1
> END AS Eficem,
> Eficem.EficemDate AS EficemDate
>
> FROM
> F0101 F1
> LEFT JOIN EsEsp300.dbo.FProspectos AS PS ON F1.ABAN8 > PS.Cliente --AND
> PS.FechaActivacion Is Not Null
> LEFT JOIN vw_UsersGF AS UGF ON F1.ABAN8 = UGF.JDECode
> LEFT JOIN tCASCases TCC ON F1.ABAN8 = TCC.BranchID
> LEFT JOIN (
> SELECT
> UGF.JDECode AS JDECode,
> A.StartDate AS EficemDate
> FROM
> cpEsp300.dbo.Agreement A
> INNER JOIN vw_UsersGF UGF ON A.IDUser = UGF.IDUser
> ) AS Eficem ON F1.ABAN8 = Eficem.JDECode
> LEFT JOIN (
> SELECT
> T1.SDAN8 AS SDAN8,
> CASE WHEN T2.Counter2 IS NULL THEN T1.Counter
> ELSE T2.Counter2
> END AS x24HrsServiceDate
> FROM
> (SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 > 3
> AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T1 FULL JOIN
> (SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2


WHERE
> SDUPC1 = 3 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T2 ON T1.SDAN8 >> > T2.SDAN82
> ) AS x24Hrs ON x24Hrs.SDAN8 = F1.ABAN8
> LEFT JOIN (
> SELECT
> T3.SDAN8 AS SDAN8,
> CASE WHEN T4.Counter2 IS NULL THEN T3.Counter
> ELSE T4.Counter2
> END AS WapServiceDate
> FROM
> (SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 > 2
> AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T3 FULL JOIN
> (SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2


WHERE
> SDUPC1 = 2 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T4 ON T3.SDAN8 >> > T4.SDAN82
> ) AS Wap ON F1.ABAN8 = Wap.SDAN8
> GROUP BY
> F1.ABAN8, Wap.wapServiceDate, x24Hrs.x24HrsServiceDate,


Eficem.JDECode,
> Eficem.EficemDate
> HAVING
> MIN(PS.FechaActivacion) Is Not Null OR
> MIN(Wap.wapServiceDate) Is Not Null OR
> MIN(x24Hrs.x24HrsServiceDate) Is Not Null OR
> MIN(UGF.StartDate) Is Not Null OR
> MIN(TCC.RegistrationDate) Is Not Null
>
> Bueno, como background, la tabla que saca los valores, con DISTINCT
> (que
> es
> algo asi como la "llave", es con lo que sabemos que registros afectar),
> produce 220000+ regs como Result Set, ahora, eso no es problema y SQL


los
> recupera en menos de 2 secs, el problema viene por que, en la tabla
> F42119,
> consiste de mas de 3 000 000+ regs, filtrandola con la llave, la
> consula
> es
> instantánea (foreignKey = 'value'), pero en el SELECT no puedo mandarle


a
> un
> SELECT anidado el valor explícito de la llave, eso lo tuve que emular


con
> el
> JOIN externo (AS Wap ON F1.ABAN8 = Wap.SDAN8), además, las tablas F4211


y
> F42119 son identicas, solo que una contiene registros históricos (La de
> los
> 3M+) y no puedo utilizar UNION, por que el UNION me producía muchisimos
> mas
> registros y hacía mas pesado el JOIN del nivel superior, y al no poder
> enviarle sino atravez del JOIN la llave contra que filtrarlo para cada
> registro en particula, me tardaba aún mas.
>
> Como sea, con varias optimizaciones al nivel donde los SELECT metían
> los
> filtrajes, lo mas que pude reducir el tiempo fue a no menos de 5 mins,


via
> un solo select, mientras que con el cursor corría en mas o menos 4
> mins,
> no
> es mucha diferencia, pero teoricamente, el tiempo crecerá


exponencialmente
> mas para el SELECT que para el CURSOR, por que el cursor manda un valor
> especifico a un SP que tiene las colsultas necesarias para generar los
> resultados que necesito
>
> En esta ocasión, al menos en las pruebas que hice, el Cursor desempeño


de
> mejor forma, y el SELECT me afectaba cuando quería correr otro query a
> alguna de las tablas, me marcaba timeout, con el Cursor corriendo no,
> igual
> se alentaba el Query, pero respondía, quizá esto ultimo fue


coincidencia,
> pero fue en mas de una ocasión. E incluso, una de las veces que lo
> corrí
> solo, el mismo parecía como bloquearse en los ultimos registros, y
> tardó
> mas
> de 20 Min.
>
> Y pues nada mas como respuesta rapida también al respecto, cuando


entablo
> una discusión sobre cursores, hay cosas que desafortunadamente de otra
> forma
> no puedes realizar, suponiendo por ejemplo, que tuvieras un sistema que
> trabajaras con probabilidades, y necesitaras generar números aleatorios
> para
> proyecciones, utilizar RAND en un SELECT pe. SELECT RAND() AS
> Tendencia,
> Field AS Factor FROM TablaHistorico, te va a utilizar el mismo número
> aleatorio atravez de todo el Result Set, lo cual, pues sería
> incorrecto.
>
> Quizá tu nunca has tenido necesidad de utilizarlos en base a los


proyectos
> que has estado, pero yo sigo pensando que, como la mayoría de las
> tecnologías un poco mas complejonas de MS, bien usados, no son un


enemigo.
> Y
> decir que su uso es patético, me parece... cierto, pero no siempre.
>
> De cualquier forma, sigo trabajando en ese query, por que me pareció
> interesante el hecho de tratar de reducir el tiempo de consulta
> moviendo
> de
> niveles el filtraje (incluso sacandolo del contexto inicial ^_^) te


aviso
> si
> pude hacer que el SELECT jalara aún mas rápido. Suerte
>
> K' Ragnarok
>
>
>
>
>
> "MAXI" wrote in message
> news:
>> Hola, podrias ampliar un poco en que te basas que los cursores ayudan?


yo
>> considero que son muy malos para tareas de produccion y que se usan
>> porque
>> es mas facil :(
>>
>> Te cuento mas, hace unos dias tuve una linda discusion con arquitectos
> .net
>> sobre este tema y demostre que el uso de cursores es patetico para
> cualquier
>> cosa
>>
>>
>>
>>
>> Maxi
>>
>> Buenos Aires - Argentina
>> Desarrollador .NET 3 Estrellas
>> Microsoft User Group (MUG)
>> Mail: Maxi_accotto[arroba]speedy.com.ar
>>
>> Msn Messenger:
>>
>> "K'" escribió en el mensaje
>> news:
>> > De hecho, si revisas los resultados de tu cursor, hace un fetch
>> > linea
> por
>> > linea, como si hicieras un SELECT por renglón
>> >
>> > Si creas el SP y lo ejecutas desde QA, debe traerte exactamente el
>> > mismo
>> > resultado (una especie de query multiple), al parecer al no
>> > descargar
> los
>> > valores en variables, el CURSOR lo toma como consultas completas
>> >
>> > Y supongo que si eso lo estás capturando con ADO, por eso solo te
> regresa
>> > un
>> > resultset
>> >
>> > En realidad no entendí bien cual es tu tirada con ese CURSOR, me


parece
>> > que
>> > puedes lograr la funcionalidad necesaria sin uso del mismo, los
>> > CURSORES
>> > no
>> > son malos usados correctamente, te ayudar a agilizar procesos, pero


mal
>> > usados, si representan un riesgo enorme, especialmente en


performance,
> así
>> > que mejor dejalos para cuando todo lo demás atenta de forma mas
>> > comprometedora en tu sistema.
>> >
>> > Si nos especificas que necesitas hacer, será mas facil apuntarte en


la
> dir
>> > para solucionar tu problema
>> >
>> > K'
>> >
>> > "Paulino Padial" wrote in message
>> > news:%23X$
>> >> Una pregunta, ¿ Te devuelve solo la ultima fila ? , puede ser que
> vayan
>> > por
>> >> ahi los tiros ;-)
>> >>
>> >>
>> >> ""


escribió
> en
>> > el
>> >> mensaje news:873301c4d0e3$d25fbde0$
>> >> > Saludos Grupo!
>> >> >
>> >> > Necesito crar una consulta como la que sigue
>> >> > ***********
>> >> > Use Pubs
>> >> > Go
>> >> > DECLARE authors_cursor CURSOR
>> >> > FOR SELECT * FROM authors
>> >> > OPEN authors_cursor
>> >> >
>> >> > FETCH NEXT FROM authors_cursor
>> >> > WHILE @@FETCH_STATUS = 0
>> >> > BEGIN
>> >> > FETCH NEXT FROM authors_cursor
>> >> > END
>> >> > CLOSE authors_cursor
>> >> > DEALLOCATE authors_cursor
>> >> > ****
>> >> >
>> >> > Cuando lo ejecuto en el analizador de consultas de SQL
>> >> > funciona perfectamente, pero cuando lo guardo en un
>> >> > procedimieto almacenado y lo llamo desde mi aplicacion me
>> >> > retorna solo la primera fila...
>> >> >
>> >> > Si alguien puede ayudarme, gracias de Antemano
>> >> >
>> >> > Fabi
>> >>
>> >>
>> >
>> >
>>
>>
>
>






Respuesta Responder a este mensaje
#4 Salvador Ramos
25/11/2004 - 19:26 | Informe spam
Otra alternativa es utilizar vistas indexadas

Un saludo
Salvador Ramos
Murcia - España
[Microsoft MVP SQL Server]
www.helpdna.net
¿ Te interesa participar en las reuniones
del grupo de Usuarios de SQL Server y .NET ?
Se harán en levante de España, (Alicante o Murcia)?

"K'" escribió en el mensaje
news:
En realidad la tabla no está normalizada, y no fui yo quien la diseñó, de
forma que no conozco bien como va a quedar al final, mi idea es que ya
normalizada va a ser aún mas rápido y si, son muchisimo mas rapidos, estoy
de acuerdo, mi otra idea de hecho fue hacer, mediante funciones de
agregado
(que es realmente lo que necesito en todas las tablas (valores mínimos))
un
espejo menor (MUCHO menor) de las tablas grandes, pero como que era mas
tardado aún no sé por que, no puedo utilizar temporales, de forma que hice
una var tipo tabla, y te digo, fue tardado

Acerca de lo del nivel de aislamiento, a que te refieres? comprendo mas o
menos, pero no me queda muy claro, de forma que no sé que responderte sin
arriegarme a meter la pata :P

K'

"Maxi" wrote in message
news:%
Hola, mira deberia tener las tablas para poder analizar mejor el caso!!


pero
me parece que hay algunas cosas que no me cierran ;)

Si la tabla tiene 3M de registros los necesitas todos?

Ademas habria que ver tema de indices y otras yerbas, pero te aseguro que


un
select tarda menos que un cursor en el 99% de los casos. Eso si, si haces


un
tableScan (que es seguro lo que te esta pasando con la de 3M) va a
demorar
un lindo ratito ;)

Tambien puedes probar de cambiar el nivel de aislamiento en la query y
probar


Salu2
Maxi


"K'" escribió en el mensaje
news:
> Saludos Maxi
>
> Yo he tenido esa discusión, pero en realidad no solo de cursores, sino


de
> la
> mayor parte de la plataforma de desarrollo de Microsoft, ja ja ja,


muchas
> personas piensan que lo mas basico es lo mejor, y no lo es en el 100%
> de
> los
> casos, como VS6 vs VS.Net, pero, acerca de SQL principalmente las
> discusiones han sido acerca de tablas temporales VS cursores para hacer
> scroll en un resultSet, de cualquier forma, aquí va por que considero


una
> ayuda benigna los cursores, precisamente ayer tuve un detalle acerca de
> eso,
> te muestro el query que estuve trabajando
>
> SELECT
> F1.ABAN8 AS ClientID,
> CASE
> WHEN MIN(PS.FechaActivacion) IS Null THEN 0
> ELSE 1
> END AS ESelling,
> MIN(PS.FechaActivacion) AS ESellingDate,
> CASE
> WHEN Wap.wapServiceDate IS Null THEN 0
> ELSE 1
> END AS Wap,
> Wap.wapServiceDate AS WapDate,
> CASE
> WHEN x24Hrs.x24HrsServiceDate IS Null THEN 0
> ELSE 1
> END AS x24Hrs,
> x24Hrs.x24HrsServiceDate AS x24HrsDate,
> CASE
> WHEN MIN(UGF.StartDate) IS Null THEN 0
> ELSE 1
> END AS CemPlus,
> MIN(UGF.StartDate) AS CemPlusDate,
> CASE
> WHEN MIN(TCC.RegistrationDate) Is Null THEN 0
> ELSE 1
> END AS CCases,
> MIN(TCC.RegistrationDate) AS CCasesDate,
> CASE
> WHEN Eficem.EficemDate IS NULL THEN 0 -- Aqui no utilizamos MIN por
> que
> siempre me trae un solo registro
> ELSE 1
> END AS Eficem,
> Eficem.EficemDate AS EficemDate
>
> FROM
> F0101 F1
> LEFT JOIN EsEsp300.dbo.FProspectos AS PS ON F1.ABAN8 > PS.Cliente --AND
> PS.FechaActivacion Is Not Null
> LEFT JOIN vw_UsersGF AS UGF ON F1.ABAN8 = UGF.JDECode
> LEFT JOIN tCASCases TCC ON F1.ABAN8 = TCC.BranchID
> LEFT JOIN (
> SELECT
> UGF.JDECode AS JDECode,
> A.StartDate AS EficemDate
> FROM
> cpEsp300.dbo.Agreement A
> INNER JOIN vw_UsersGF UGF ON A.IDUser = UGF.IDUser
> ) AS Eficem ON F1.ABAN8 = Eficem.JDECode
> LEFT JOIN (
> SELECT
> T1.SDAN8 AS SDAN8,
> CASE WHEN T2.Counter2 IS NULL THEN T1.Counter
> ELSE T2.Counter2
> END AS x24HrsServiceDate
> FROM
> (SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 > 3
> AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T1 FULL JOIN
> (SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2


WHERE
> SDUPC1 = 3 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T2 ON T1.SDAN8 >> > T2.SDAN82
> ) AS x24Hrs ON x24Hrs.SDAN8 = F1.ABAN8
> LEFT JOIN (
> SELECT
> T3.SDAN8 AS SDAN8,
> CASE WHEN T4.Counter2 IS NULL THEN T3.Counter
> ELSE T4.Counter2
> END AS WapServiceDate
> FROM
> (SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 > 2
> AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T3 FULL JOIN
> (SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2


WHERE
> SDUPC1 = 2 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T4 ON T3.SDAN8 >> > T4.SDAN82
> ) AS Wap ON F1.ABAN8 = Wap.SDAN8
> GROUP BY
> F1.ABAN8, Wap.wapServiceDate, x24Hrs.x24HrsServiceDate,


Eficem.JDECode,
> Eficem.EficemDate
> HAVING
> MIN(PS.FechaActivacion) Is Not Null OR
> MIN(Wap.wapServiceDate) Is Not Null OR
> MIN(x24Hrs.x24HrsServiceDate) Is Not Null OR
> MIN(UGF.StartDate) Is Not Null OR
> MIN(TCC.RegistrationDate) Is Not Null
>
> Bueno, como background, la tabla que saca los valores, con DISTINCT
> (que
> es
> algo asi como la "llave", es con lo que sabemos que registros afectar),
> produce 220000+ regs como Result Set, ahora, eso no es problema y SQL


los
> recupera en menos de 2 secs, el problema viene por que, en la tabla
> F42119,
> consiste de mas de 3 000 000+ regs, filtrandola con la llave, la
> consula
> es
> instantánea (foreignKey = 'value'), pero en el SELECT no puedo mandarle


a
> un
> SELECT anidado el valor explícito de la llave, eso lo tuve que emular


con
> el
> JOIN externo (AS Wap ON F1.ABAN8 = Wap.SDAN8), además, las tablas F4211


y
> F42119 son identicas, solo que una contiene registros históricos (La de
> los
> 3M+) y no puedo utilizar UNION, por que el UNION me producía muchisimos
> mas
> registros y hacía mas pesado el JOIN del nivel superior, y al no poder
> enviarle sino atravez del JOIN la llave contra que filtrarlo para cada
> registro en particula, me tardaba aún mas.
>
> Como sea, con varias optimizaciones al nivel donde los SELECT metían
> los
> filtrajes, lo mas que pude reducir el tiempo fue a no menos de 5 mins,


via
> un solo select, mientras que con el cursor corría en mas o menos 4
> mins,
> no
> es mucha diferencia, pero teoricamente, el tiempo crecerá


exponencialmente
> mas para el SELECT que para el CURSOR, por que el cursor manda un valor
> especifico a un SP que tiene las colsultas necesarias para generar los
> resultados que necesito
>
> En esta ocasión, al menos en las pruebas que hice, el Cursor desempeño


de
> mejor forma, y el SELECT me afectaba cuando quería correr otro query a
> alguna de las tablas, me marcaba timeout, con el Cursor corriendo no,
> igual
> se alentaba el Query, pero respondía, quizá esto ultimo fue


coincidencia,
> pero fue en mas de una ocasión. E incluso, una de las veces que lo
> corrí
> solo, el mismo parecía como bloquearse en los ultimos registros, y
> tardó
> mas
> de 20 Min.
>
> Y pues nada mas como respuesta rapida también al respecto, cuando


entablo
> una discusión sobre cursores, hay cosas que desafortunadamente de otra
> forma
> no puedes realizar, suponiendo por ejemplo, que tuvieras un sistema que
> trabajaras con probabilidades, y necesitaras generar números aleatorios
> para
> proyecciones, utilizar RAND en un SELECT pe. SELECT RAND() AS
> Tendencia,
> Field AS Factor FROM TablaHistorico, te va a utilizar el mismo número
> aleatorio atravez de todo el Result Set, lo cual, pues sería
> incorrecto.
>
> Quizá tu nunca has tenido necesidad de utilizarlos en base a los


proyectos
> que has estado, pero yo sigo pensando que, como la mayoría de las
> tecnologías un poco mas complejonas de MS, bien usados, no son un


enemigo.
> Y
> decir que su uso es patético, me parece... cierto, pero no siempre.
>
> De cualquier forma, sigo trabajando en ese query, por que me pareció
> interesante el hecho de tratar de reducir el tiempo de consulta
> moviendo
> de
> niveles el filtraje (incluso sacandolo del contexto inicial ^_^) te


aviso
> si
> pude hacer que el SELECT jalara aún mas rápido. Suerte
>
> K' Ragnarok
>
>
>
>
>
> "MAXI" wrote in message
> news:
>> Hola, podrias ampliar un poco en que te basas que los cursores ayudan?


yo
>> considero que son muy malos para tareas de produccion y que se usan
>> porque
>> es mas facil :(
>>
>> Te cuento mas, hace unos dias tuve una linda discusion con arquitectos
> .net
>> sobre este tema y demostre que el uso de cursores es patetico para
> cualquier
>> cosa
>>
>>
>>
>>
>> Maxi
>>
>> Buenos Aires - Argentina
>> Desarrollador .NET 3 Estrellas
>> Microsoft User Group (MUG)
>> Mail: Maxi_accotto[arroba]speedy.com.ar
>>
>> Msn Messenger:
>>
>> "K'" escribió en el mensaje
>> news:
>> > De hecho, si revisas los resultados de tu cursor, hace un fetch
>> > linea
> por
>> > linea, como si hicieras un SELECT por renglón
>> >
>> > Si creas el SP y lo ejecutas desde QA, debe traerte exactamente el
>> > mismo
>> > resultado (una especie de query multiple), al parecer al no
>> > descargar
> los
>> > valores en variables, el CURSOR lo toma como consultas completas
>> >
>> > Y supongo que si eso lo estás capturando con ADO, por eso solo te
> regresa
>> > un
>> > resultset
>> >
>> > En realidad no entendí bien cual es tu tirada con ese CURSOR, me


parece
>> > que
>> > puedes lograr la funcionalidad necesaria sin uso del mismo, los
>> > CURSORES
>> > no
>> > son malos usados correctamente, te ayudar a agilizar procesos, pero


mal
>> > usados, si representan un riesgo enorme, especialmente en


performance,
> así
>> > que mejor dejalos para cuando todo lo demás atenta de forma mas
>> > comprometedora en tu sistema.
>> >
>> > Si nos especificas que necesitas hacer, será mas facil apuntarte en


la
> dir
>> > para solucionar tu problema
>> >
>> > K'
>> >
>> > "Paulino Padial" wrote in message
>> > news:%23X$
>> >> Una pregunta, ¿ Te devuelve solo la ultima fila ? , puede ser que
> vayan
>> > por
>> >> ahi los tiros ;-)
>> >>
>> >>
>> >> ""


escribió
> en
>> > el
>> >> mensaje news:873301c4d0e3$d25fbde0$
>> >> > Saludos Grupo!
>> >> >
>> >> > Necesito crar una consulta como la que sigue
>> >> > ***********
>> >> > Use Pubs
>> >> > Go
>> >> > DECLARE authors_cursor CURSOR
>> >> > FOR SELECT * FROM authors
>> >> > OPEN authors_cursor
>> >> >
>> >> > FETCH NEXT FROM authors_cursor
>> >> > WHILE @@FETCH_STATUS = 0
>> >> > BEGIN
>> >> > FETCH NEXT FROM authors_cursor
>> >> > END
>> >> > CLOSE authors_cursor
>> >> > DEALLOCATE authors_cursor
>> >> > ****
>> >> >
>> >> > Cuando lo ejecuto en el analizador de consultas de SQL
>> >> > funciona perfectamente, pero cuando lo guardo en un
>> >> > procedimieto almacenado y lo llamo desde mi aplicacion me
>> >> > retorna solo la primera fila...
>> >> >
>> >> > Si alguien puede ayudarme, gracias de Antemano
>> >> >
>> >> > Fabi
>> >>
>> >>
>> >
>> >
>>
>>
>
>






Respuesta Responder a este mensaje
#5 Javier Loria
26/11/2004 - 17:42 | Informe spam
Hola:
No soy Maxi, pero prodrias probar si el siguiente codigo, obtiene los
mismos resultados y mejor desempeno?
==SELECT F1.ABAN8 AS ClientID
, CASE WHEN MIN(PS.FechaActivacion) IS Null
THEN 0
ELSE 1
END AS ESelling
, MIN(PS.FechaActivacion) AS ESellingDate
, -- WAP
CASE WHEN x24HrsWap.wapServiceDate IS Null
THEN 0
ELSE 1
END AS Wap
, x24HrsWap.wapServiceDate AS WapDate
, -- 24Hrs
CASE
WHEN x24HrsWap.x24HrsServiceDate IS Null
THEN 0
ELSE 1 END AS x24Hrs
, x24HrsWap.x24HrsServiceDate AS x24HrsDate
, -- CEMPlus
CASE WHEN MIN(UGF.StartDate) IS Null
THEN 0
ELSE 1 END AS CemPlus
, MIN(UGF.StartDate) AS CemPlusDate
, --Cases
CASE WHEN MIN(TCC.RegistrationDate) Is Null
THEN 0
ELSE 1 END AS CCases
, MIN(TCC.RegistrationDate) AS CCasesDate
, CASE WHEN Agr.StartDate IS NULL
THEN 0 -- Aqui no utilizamos MIN por que siempre me trae un solo registro
ELSE 1 END AS Eficem
, Agr.StartDate AS EficemDate
FROM F0101 F1
LEFT JOIN EsEsp300.dbo.FProspectos AS PS
ON F1.ABAN8 = PS.Cliente --AND
PS.FechaActivacion Is Not Null
LEFT JOIN vw_UsersGF AS UGF
ON F1.ABAN8 = UGF.JDECode
LEFT JOIN tCASCases TCC
ON F1.ABAN8 = TCC.BranchID
LEFT JOIN vw_UsersGF AS UGF
ON F1.ABAN8 = UGF.JDECode
LEFT JOIN cpEsp300.dbo.Agreement AS Agr
ON Agr.IDUser = UGF.IDUser
LEFT JOIN (SELECT T1.SDAN8 AS SDAN8
, COALESCE(T2.X24Hrs, T1.X24Hrs) AS x24HrsServiceDate
, COALESCE(T2.Wap , T1.Wap) AS x24HrsServiceDate
FROM
(SELECT SDAN8
, MIN(CASE WHEN SDUPC1=3 THEN SDTRDJ END) AS X24Hrs
, MIN(CASE WHEN SDUPC1=2 THEN SDTRDJ END) AS Wap
FROM F4211
WHERE (SDUPC1 = 3 OR SDUPC1 =2) AND
AND SDTRDJ Is Not Null
GROUP BY SDAN8) AS T1
FULL JOIN
(SELECT SDAN8 AS SDAN82
, MIN(CASE WHEN SDUPC1=3 THEN SDTRDJ END) AS X24Hrs
, MIN(CASE WHEN SDUPC1=2 THEN SDTRDJ END) AS Wap
FROM F42119
WHERE (SDUPC1 = 3 OR SDUPC1 =2)
AND SDTRDJ Is Not Null
GROUP BY SDAN8) AS T2
ON T1.SDAN8 =T2.SDAN82) AS x24HrsWap
ON x24HrsWap.SDAN8 = F1.ABAN8
GROUP BY F1.ABAN8, x24HrsWap.wapServiceDate, x24HrsWap.x24HrsServiceDate,
UGF.JDECode, Agr.StartDate
HAVING MIN(PS.FechaActivacion) Is Not Null OR
MIN(Wap.wapServiceDate) Is Not Null OR
MIN(x24HrsWap.x24HrsServiceDate) Is Not Null OR
MIN(UGF.StartDate) Is Not Null OR
MIN(TCC.RegistrationDate) Is Not Null

== Basicamente, trate de "aplanar" algunas de las consultas y evitar una
consulta. Espero que no tenga errores de sintaxis ya que esta escrito sin el
codigo de las tablas, lo que hace muy dificil la
Suerte,


Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda

"K'" wrote in message
news:
Saludos Maxi

Yo he tenido esa discusión, pero en realidad no solo de cursores, sino de


la
mayor parte de la plataforma de desarrollo de Microsoft, ja ja ja, muchas
personas piensan que lo mas basico es lo mejor, y no lo es en el 100% de


los
casos, como VS6 vs VS.Net, pero, acerca de SQL principalmente las
discusiones han sido acerca de tablas temporales VS cursores para hacer
scroll en un resultSet, de cualquier forma, aquí va por que considero una
ayuda benigna los cursores, precisamente ayer tuve un detalle acerca de


eso,
te muestro el query que estuve trabajando

SELECT
F1.ABAN8 AS ClientID,
CASE
WHEN MIN(PS.FechaActivacion) IS Null THEN 0
ELSE 1
END AS ESelling,
MIN(PS.FechaActivacion) AS ESellingDate,
CASE
WHEN Wap.wapServiceDate IS Null THEN 0
ELSE 1
END AS Wap,
Wap.wapServiceDate AS WapDate,
CASE
WHEN x24Hrs.x24HrsServiceDate IS Null THEN 0
ELSE 1
END AS x24Hrs,
x24Hrs.x24HrsServiceDate AS x24HrsDate,
CASE
WHEN MIN(UGF.StartDate) IS Null THEN 0
ELSE 1
END AS CemPlus,
MIN(UGF.StartDate) AS CemPlusDate,
CASE
WHEN MIN(TCC.RegistrationDate) Is Null THEN 0
ELSE 1
END AS CCases,
MIN(TCC.RegistrationDate) AS CCasesDate,
CASE
WHEN Eficem.EficemDate IS NULL THEN 0 -- Aqui no utilizamos MIN por


que
siempre me trae un solo registro
ELSE 1
END AS Eficem,
Eficem.EficemDate AS EficemDate

FROM
F0101 F1
LEFT JOIN EsEsp300.dbo.FProspectos AS PS ON F1.ABAN8 = PS.Cliente --AND
PS.FechaActivacion Is Not Null
LEFT JOIN vw_UsersGF AS UGF ON F1.ABAN8 = UGF.JDECode
LEFT JOIN tCASCases TCC ON F1.ABAN8 = TCC.BranchID
LEFT JOIN (
SELECT
UGF.JDECode AS JDECode,
A.StartDate AS EficemDate
FROM
cpEsp300.dbo.Agreement A
INNER JOIN vw_UsersGF UGF ON A.IDUser = UGF.IDUser
) AS Eficem ON F1.ABAN8 = Eficem.JDECode
LEFT JOIN (
SELECT
T1.SDAN8 AS SDAN8,
CASE WHEN T2.Counter2 IS NULL THEN T1.Counter
ELSE T2.Counter2
END AS x24HrsServiceDate
FROM
(SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 = 3
AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T1 FULL JOIN
(SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2


WHERE
SDUPC1 = 3 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T2 ON T1.SDAN8 > T2.SDAN82
) AS x24Hrs ON x24Hrs.SDAN8 = F1.ABAN8
LEFT JOIN (
SELECT
T3.SDAN8 AS SDAN8,
CASE WHEN T4.Counter2 IS NULL THEN T3.Counter
ELSE T4.Counter2
END AS WapServiceDate
FROM
(SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 = 2
AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T3 FULL JOIN
(SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2


WHERE
SDUPC1 = 2 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T4 ON T3.SDAN8 > T4.SDAN82
) AS Wap ON F1.ABAN8 = Wap.SDAN8
GROUP BY
F1.ABAN8, Wap.wapServiceDate, x24Hrs.x24HrsServiceDate, Eficem.JDECode,
Eficem.EficemDate
HAVING
MIN(PS.FechaActivacion) Is Not Null OR
MIN(Wap.wapServiceDate) Is Not Null OR
MIN(x24Hrs.x24HrsServiceDate) Is Not Null OR
MIN(UGF.StartDate) Is Not Null OR
MIN(TCC.RegistrationDate) Is Not Null

Bueno, como background, la tabla que saca los valores, con DISTINCT (que


es
algo asi como la "llave", es con lo que sabemos que registros afectar),
produce 220000+ regs como Result Set, ahora, eso no es problema y SQL los
recupera en menos de 2 secs, el problema viene por que, en la tabla


F42119,
consiste de mas de 3 000 000+ regs, filtrandola con la llave, la consula


es
instantánea (foreignKey = 'value'), pero en el SELECT no puedo mandarle a


un
SELECT anidado el valor explícito de la llave, eso lo tuve que emular con


el
JOIN externo (AS Wap ON F1.ABAN8 = Wap.SDAN8), además, las tablas F4211 y
F42119 son identicas, solo que una contiene registros históricos (La de


los
3M+) y no puedo utilizar UNION, por que el UNION me producía muchisimos


mas
registros y hacía mas pesado el JOIN del nivel superior, y al no poder
enviarle sino atravez del JOIN la llave contra que filtrarlo para cada
registro en particula, me tardaba aún mas.

Como sea, con varias optimizaciones al nivel donde los SELECT metían los
filtrajes, lo mas que pude reducir el tiempo fue a no menos de 5 mins, via
un solo select, mientras que con el cursor corría en mas o menos 4 mins,


no
es mucha diferencia, pero teoricamente, el tiempo crecerá exponencialmente
mas para el SELECT que para el CURSOR, por que el cursor manda un valor
especifico a un SP que tiene las colsultas necesarias para generar los
resultados que necesito

En esta ocasión, al menos en las pruebas que hice, el Cursor desempeño de
mejor forma, y el SELECT me afectaba cuando quería correr otro query a
alguna de las tablas, me marcaba timeout, con el Cursor corriendo no,


igual
se alentaba el Query, pero respondía, quizá esto ultimo fue coincidencia,
pero fue en mas de una ocasión. E incluso, una de las veces que lo corrí
solo, el mismo parecía como bloquearse en los ultimos registros, y tardó


mas
de 20 Min.

Y pues nada mas como respuesta rapida también al respecto, cuando entablo
una discusión sobre cursores, hay cosas que desafortunadamente de otra


forma
no puedes realizar, suponiendo por ejemplo, que tuvieras un sistema que
trabajaras con probabilidades, y necesitaras generar números aleatorios


para
proyecciones, utilizar RAND en un SELECT pe. SELECT RAND() AS Tendencia,
Field AS Factor FROM TablaHistorico, te va a utilizar el mismo número
aleatorio atravez de todo el Result Set, lo cual, pues sería incorrecto.

Quizá tu nunca has tenido necesidad de utilizarlos en base a los proyectos
que has estado, pero yo sigo pensando que, como la mayoría de las
tecnologías un poco mas complejonas de MS, bien usados, no son un enemigo.


Y
decir que su uso es patético, me parece... cierto, pero no siempre.

De cualquier forma, sigo trabajando en ese query, por que me pareció
interesante el hecho de tratar de reducir el tiempo de consulta moviendo


de
niveles el filtraje (incluso sacandolo del contexto inicial ^_^) te aviso


si
pude hacer que el SELECT jalara aún mas rápido. Suerte

K' Ragnarok





"MAXI" wrote in message
news:
> Hola, podrias ampliar un poco en que te basas que los cursores ayudan?


yo
> considero que son muy malos para tareas de produccion y que se usan


porque
> es mas facil :(
>
> Te cuento mas, hace unos dias tuve una linda discusion con arquitectos
.net
> sobre este tema y demostre que el uso de cursores es patetico para
cualquier
> cosa
>
>
>
>
> Maxi
>
> Buenos Aires - Argentina
> Desarrollador .NET 3 Estrellas
> Microsoft User Group (MUG)
> Mail: Maxi_accotto[arroba]speedy.com.ar
>
> Msn Messenger:
>
> "K'" escribió en el mensaje
> news:
> > De hecho, si revisas los resultados de tu cursor, hace un fetch linea
por
> > linea, como si hicieras un SELECT por renglón
> >
> > Si creas el SP y lo ejecutas desde QA, debe traerte exactamente el


mismo
> > resultado (una especie de query multiple), al parecer al no descargar
los
> > valores en variables, el CURSOR lo toma como consultas completas
> >
> > Y supongo que si eso lo estás capturando con ADO, por eso solo te
regresa
> > un
> > resultset
> >
> > En realidad no entendí bien cual es tu tirada con ese CURSOR, me


parece
> > que
> > puedes lograr la funcionalidad necesaria sin uso del mismo, los


CURSORES
> > no
> > son malos usados correctamente, te ayudar a agilizar procesos, pero


mal
> > usados, si representan un riesgo enorme, especialmente en performance,
así
> > que mejor dejalos para cuando todo lo demás atenta de forma mas
> > comprometedora en tu sistema.
> >
> > Si nos especificas que necesitas hacer, será mas facil apuntarte en la
dir
> > para solucionar tu problema
> >
> > K'
> >
> > "Paulino Padial" wrote in message
> > news:%23X$
> >> Una pregunta, ¿ Te devuelve solo la ultima fila ? , puede ser que
vayan
> > por
> >> ahi los tiros ;-)
> >>
> >>
> >> ""


escribió
en
> > el
> >> mensaje news:873301c4d0e3$d25fbde0$
> >> > Saludos Grupo!
> >> >
> >> > Necesito crar una consulta como la que sigue
> >> > ***********
> >> > Use Pubs
> >> > Go
> >> > DECLARE authors_cursor CURSOR
> >> > FOR SELECT * FROM authors
> >> > OPEN authors_cursor
> >> >
> >> > FETCH NEXT FROM authors_cursor
> >> > WHILE @@FETCH_STATUS = 0
> >> > BEGIN
> >> > FETCH NEXT FROM authors_cursor
> >> > END
> >> > CLOSE authors_cursor
> >> > DEALLOCATE authors_cursor
> >> > ****
> >> >
> >> > Cuando lo ejecuto en el analizador de consultas de SQL
> >> > funciona perfectamente, pero cuando lo guardo en un
> >> > procedimieto almacenado y lo llamo desde mi aplicacion me
> >> > retorna solo la primera fila...
> >> >
> >> > Si alguien puede ayudarme, gracias de Antemano
> >> >
> >> > Fabi
> >>
> >>
> >
> >
>
>


email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida