Ciclos en T-SQL?

25/09/2004 - 04:33 por Leonardo Azpurua | Informe spam
Hola.

Ayer estaba instalando donde un cliente un antiguo sistema escrito en "C"
para MSDOS/Netware mientras una colega hacia unos ajustes en sus sistema de
negocios, escrito con las herramientas de desarrollo de Oracle. Como nunca
había tenido ningun contacto con Oracle, le pedí que me dejara mirar algunos
SPs, y vi una cosa que casi me mata de la envidia:

FOR P IN (SELECT C1, C2, C3 FROM T1)
FOR G IN (SELECT D1, D2, D3 FROM T2 WHERE D1 = P.C1)
...
END LOOP
END LOOP
(no estoy seguro de que los END LOOP de verdad se escriban asi, pero esa es
la idea).

A pesar de haber tenido algunas dificultades sigo aceptando el dogma de que
todo lo que puede ser expresado mediante estructuras de control de flujo
puede expresarse usando instrucciones de manipulacion de datos. Pero qué
cantidad de trabajo podría uno ahorrarse si pudiera disponer de una
construccion equivalente en T-SQL.

En cuanto llegué a casa revise los BOL, y no encontre nada parecido.

¿De verdad no hay nada parecido en T-SQL? ¿Tal vez alguna manera de
simularlo?

Salud!

Leonardo

Preguntas similare

Leer las respuestas

#1 Gustavo Larriera [MVP]
25/09/2004 - 04:37 | Informe spam
La construcción FOR LOOP de Oracle PL/SQL es la forma implícita de manejar
cursores. En T-SQL eso se hace con cursores explícitos. Compara estos dos
ejemplos:

ORACLE PL/SQL:

begin
FOR r IN (
SELECT ename
from emp
where ename < 'C'
order by 1) LOOP
dbms_output.put_line(r.ename);
END LOOP;
end;

SQL SERVER T-SQL:

declare @lname varchar(30)
DECLARE c1 cursor FOR
select lname
from employee
where lname < 'C'
order by 1
OPEN c1
FETCH c1 into @lname
WHILE @@FETCH_STATUS = 0
begin
print @lname
FETCH c1 into @lname
end
CLOSE c1
DEALLOCATE c1

saludos
gux

Gustavo Larriera, MVP
Uruguay LatAm
http://sqljunkies.com/weblog/gux/
Este mensaje se proporciona "COMO ESTA" sin garantias y no otorga ningun
derecho / This posting is provided "AS IS" with no warranties, and confers
no rights.
"Leonardo Azpurua" <l e o n a r d o (arroba) m v p s (punto) o r g> wrote in
message news:%
Hola.

Ayer estaba instalando donde un cliente un antiguo sistema escrito en "C"
para MSDOS/Netware mientras una colega hacia unos ajustes en sus sistema
de
negocios, escrito con las herramientas de desarrollo de Oracle. Como nunca
había tenido ningun contacto con Oracle, le pedí que me dejara mirar
algunos
SPs, y vi una cosa que casi me mata de la envidia:

FOR P IN (SELECT C1, C2, C3 FROM T1)
FOR G IN (SELECT D1, D2, D3 FROM T2 WHERE D1 = P.C1)
...
END LOOP
END LOOP
(no estoy seguro de que los END LOOP de verdad se escriban asi, pero esa
es
la idea).

A pesar de haber tenido algunas dificultades sigo aceptando el dogma de
que
todo lo que puede ser expresado mediante estructuras de control de flujo
puede expresarse usando instrucciones de manipulacion de datos. Pero qué
cantidad de trabajo podría uno ahorrarse si pudiera disponer de una
construccion equivalente en T-SQL.

En cuanto llegué a casa revise los BOL, y no encontre nada parecido.

¿De verdad no hay nada parecido en T-SQL? ¿Tal vez alguna manera de
simularlo?

Salud!

Leonardo


Respuesta Responder a este mensaje
#2 Leonardo Azpurua
25/09/2004 - 05:16 | Informe spam
"Gustavo Larriera [MVP]" escribió en el mensaje
news:%23v$
La construcción FOR LOOP de Oracle PL/SQL es la forma implícita de manejar
cursores. En T-SQL eso se hace con cursores explícitos. Compara estos dos
ejemplos:

ORACLE PL/SQL:

begin
FOR r IN (
SELECT ename
from emp
where ename < 'C'
order by 1) LOOP
dbms_output.put_line(r.ename);
END LOOP;
end;

SQL SERVER T-SQL:

declare @lname varchar(30)
DECLARE c1 cursor FOR
select lname
from employee
where lname < 'C'
order by 1
OPEN c1
FETCH c1 into @lname
WHILE @@FETCH_STATUS = 0
begin
print @lname
FETCH c1 into @lname
end
CLOSE c1
DEALLOCATE c1



Hola, Gustavo

Y gracias por la respuesta.

He leido cantidad de veces que no es conveniente utilizar cursores en los
SPs (aunque hay cosas que desde el punto de vista del texto, y de la logica,
se facilitarian muchísimo). Pero tembien he descubierto que la mayoria de
las cosas que se escuchan son repeticiones generalmente aceptada de una
mentira originaria. ¿Es realmente inconveniente el uso de cursores en los
SPs? ¿Por qué?

Con respecto al ejemplo, si en vez del nombre quisieramos el Nombre y el
Cargo, poriamos escribir?

declare @lname varchar(30), @Cargo vachar(8)

DECLARE c1 cursor FOR
select lname, Cargo
from employee
where lname < 'C'
order by 1
OPEN c1
FETCH c1 into @lname, @Cargo
WHILE @@FETCH_STATUS = 0
begin
print @lname + ' ES UN ' + @Cargo
FETCH c1 into @lname, @Cargo
end
CLOSE c1
DEALLOCATE c1

es decir, ¿incluimos tantas columnas como necesitemos en la sentencia origen
del cursor, y luego obtenemos esos campos asociandolos con variables en la
posicion ordinal correspondiente del FETCH?

Si no, ¿como?

Gracias,

Leonardo
mvp vb

P.S.: La verdad, en este caso concreto, me gusta mas la implementacon en PL.
Respuesta Responder a este mensaje
#3 Guillermo Roldán
25/09/2004 - 13:17 | Informe spam
Independientemente del motor de base de datos, la utilización de cursores
siempre penaliza el rendimiento, existiendo además posibilidades de que se
produzcan bloqueos no deseados, o incluso interbloqueos. Como para cada
registro del cursor se realizará una lógica, esto supone un consumo de CPU e
incluso de memoria, dependiendo del caso.

Si deseas recuperar varios campos de una SELECT con un cursor, no tendrás
problema en T-SQL, aunque ahora no recuerdo la sintaxis.

Para facilitarte la tarea de realizar cursores, puedes seguir los siguientes
pasos desde el Analizador de Consultas para utilizar plantillas predefinidas
con código T-SQL, para que las modifiques a tu antojo:
- Archivo -> Nuevo
- Abrimos la carpeta "Using Cursor" y seleccionamos la plantilla que
deseemos.

Espero te sea de ayuda.

Saludos,
Guillermo Roldán
MCDBA, MCSE, MCSA
Madrid - Spain



"Leonardo Azpurua" <l e o n a r d o (arroba) m v p s (punto) o r g> escribió
en el mensaje news:

"Gustavo Larriera [MVP]" escribió en el mensaje
news:%23v$
> La construcción FOR LOOP de Oracle PL/SQL es la forma implícita de


manejar
> cursores. En T-SQL eso se hace con cursores explícitos. Compara estos


dos
> ejemplos:
>
> ORACLE PL/SQL:
>
> begin
> FOR r IN (
> SELECT ename
> from emp
> where ename < 'C'
> order by 1) LOOP
> dbms_output.put_line(r.ename);
> END LOOP;
> end;
>
> SQL SERVER T-SQL:
>
> declare @lname varchar(30)
> DECLARE c1 cursor FOR
> select lname
> from employee
> where lname < 'C'
> order by 1
> OPEN c1
> FETCH c1 into @lname
> WHILE @@FETCH_STATUS = 0
> begin
> print @lname
> FETCH c1 into @lname
> end
> CLOSE c1
> DEALLOCATE c1

Hola, Gustavo

Y gracias por la respuesta.

He leido cantidad de veces que no es conveniente utilizar cursores en los
SPs (aunque hay cosas que desde el punto de vista del texto, y de la


logica,
se facilitarian muchísimo). Pero tembien he descubierto que la mayoria de
las cosas que se escuchan son repeticiones generalmente aceptada de una
mentira originaria. ¿Es realmente inconveniente el uso de cursores en los
SPs? ¿Por qué?

Con respecto al ejemplo, si en vez del nombre quisieramos el Nombre y el
Cargo, poriamos escribir?

declare @lname varchar(30), @Cargo vachar(8)

DECLARE c1 cursor FOR
select lname, Cargo
from employee
where lname < 'C'
order by 1
OPEN c1
FETCH c1 into @lname, @Cargo
WHILE @@FETCH_STATUS = 0
begin
print @lname + ' ES UN ' + @Cargo
FETCH c1 into @lname, @Cargo
end
CLOSE c1
DEALLOCATE c1

es decir, ¿incluimos tantas columnas como necesitemos en la sentencia


origen
del cursor, y luego obtenemos esos campos asociandolos con variables en la
posicion ordinal correspondiente del FETCH?

Si no, ¿como?

Gracias,

Leonardo
mvp vb

P.S.: La verdad, en este caso concreto, me gusta mas la implementacon en


PL.


Respuesta Responder a este mensaje
#4 MAXI
25/09/2004 - 15:36 | Informe spam
Leo, los motores de BDD (cualquiera) estan pensados y optimizados para
trabajar con conjunto de datos y no registro a registro (cursores)

El uso de cursores en motores se da porque muchos años de Developer en
Access, Fox, etc han hecho que los desarrolladores se acostunbren a trabajar
asi, pero en motores corporativos como SQL u otro, esto es terrible.

La performance es muy mala y se generan muchos bloqueos.

Si quieres probarlo es simple:

Armate una tabla con 1.000.000 de registros cualquiera, luego los borras
asi:

1) armas un cursor y haces Delete from tabla where id = id_cursor
2) delete from tabla

y decime cual tarda mas ;-), esto mismo pasa con cualquier cursor que uses ,
en cualquier motor que uses.

EL tema Leo, es que hay que cambiar la forma de pensar, y esto lleva un
tiempo de maduracion nada simple, pero para que no te desesperes te cuento:

En mis querys o procesos no he usado nunca un cursor! claro s mucho mas
dificil pensar la instruccion para que lo haga en conjunto de registros,
hasta es mas dificil de interpretar por los otros (los que estan
acostumbrados a usar cursores)

y para mas info (que seguro la tenes ya ;-) ADO.NET 2.0 NO tendra disponible
el uso de cursores!!! te dice algo esto?


Un abrazo!!!




Maxi

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

Msn Messager:

"Leonardo Azpurua" <l e o n a r d o (arroba) m v p s (punto) o r g> escribió
en el mensaje news:

"Gustavo Larriera [MVP]" escribió en el mensaje
news:%23v$
La construcción FOR LOOP de Oracle PL/SQL es la forma implícita de
manejar
cursores. En T-SQL eso se hace con cursores explícitos. Compara estos dos
ejemplos:

ORACLE PL/SQL:

begin
FOR r IN (
SELECT ename
from emp
where ename < 'C'
order by 1) LOOP
dbms_output.put_line(r.ename);
END LOOP;
end;

SQL SERVER T-SQL:

declare @lname varchar(30)
DECLARE c1 cursor FOR
select lname
from employee
where lname < 'C'
order by 1
OPEN c1
FETCH c1 into @lname
WHILE @@FETCH_STATUS = 0
begin
print @lname
FETCH c1 into @lname
end
CLOSE c1
DEALLOCATE c1



Hola, Gustavo

Y gracias por la respuesta.

He leido cantidad de veces que no es conveniente utilizar cursores en los
SPs (aunque hay cosas que desde el punto de vista del texto, y de la
logica,
se facilitarian muchísimo). Pero tembien he descubierto que la mayoria de
las cosas que se escuchan son repeticiones generalmente aceptada de una
mentira originaria. ¿Es realmente inconveniente el uso de cursores en los
SPs? ¿Por qué?

Con respecto al ejemplo, si en vez del nombre quisieramos el Nombre y el
Cargo, poriamos escribir?

declare @lname varchar(30), @Cargo vachar(8)

DECLARE c1 cursor FOR
select lname, Cargo
from employee
where lname < 'C'
order by 1
OPEN c1
FETCH c1 into @lname, @Cargo
WHILE @@FETCH_STATUS = 0
begin
print @lname + ' ES UN ' + @Cargo
FETCH c1 into @lname, @Cargo
end
CLOSE c1
DEALLOCATE c1

es decir, ¿incluimos tantas columnas como necesitemos en la sentencia
origen
del cursor, y luego obtenemos esos campos asociandolos con variables en la
posicion ordinal correspondiente del FETCH?

Si no, ¿como?

Gracias,

Leonardo
mvp vb

P.S.: La verdad, en este caso concreto, me gusta mas la implementacon en
PL.


Respuesta Responder a este mensaje
#5 Gustavo Larriera [MVP]
25/09/2004 - 15:51 | Informe spam
Hola Leonardo,

sí, si deseas acceder a varias columnas, las declaras, las usas en la SELECT
que define el cursor y las cargas en cada iteración usando FETCH.

Respecto al uso de cursores: El uso de cursores suele ser un alto consumidor
de recursos del servidor de bases de datos, aunque hay sistemas que los
toleran mejor que otros. En el caso de SQL Server, los cursores suelen ser
una mala idea.

IMHO no se deberían usar cursores cuando la operación puede lograrse
directamente usando operadores relacionales. Lo que sucede es que para
muchos programadores les resulta más fácil de utilizar los cursores que
hacer una consulta compleja equivalente.

Muchísimos saludos,
gux

Gustavo Larriera, MVP
Uruguay LatAm
http://sqljunkies.com/weblog/gux/
Este mensaje se proporciona "COMO ESTA" sin garantias y no otorga ningun
derecho / This posting is provided "AS IS" with no warranties, and confers
no rights.
"Leonardo Azpurua" <l e o n a r d o (arroba) m v p s (punto) o r g> wrote in
message news:

"Gustavo Larriera [MVP]" escribió en el mensaje
news:%23v$
La construcción FOR LOOP de Oracle PL/SQL es la forma implícita de
manejar
cursores. En T-SQL eso se hace con cursores explícitos. Compara estos dos
ejemplos:

ORACLE PL/SQL:

begin
FOR r IN (
SELECT ename
from emp
where ename < 'C'
order by 1) LOOP
dbms_output.put_line(r.ename);
END LOOP;
end;

SQL SERVER T-SQL:

declare @lname varchar(30)
DECLARE c1 cursor FOR
select lname
from employee
where lname < 'C'
order by 1
OPEN c1
FETCH c1 into @lname
WHILE @@FETCH_STATUS = 0
begin
print @lname
FETCH c1 into @lname
end
CLOSE c1
DEALLOCATE c1



Hola, Gustavo

Y gracias por la respuesta.

He leido cantidad de veces que no es conveniente utilizar cursores en los
SPs (aunque hay cosas que desde el punto de vista del texto, y de la
logica,
se facilitarian muchísimo). Pero tembien he descubierto que la mayoria de
las cosas que se escuchan son repeticiones generalmente aceptada de una
mentira originaria. ¿Es realmente inconveniente el uso de cursores en los
SPs? ¿Por qué?

Con respecto al ejemplo, si en vez del nombre quisieramos el Nombre y el
Cargo, poriamos escribir?

declare @lname varchar(30), @Cargo vachar(8)

DECLARE c1 cursor FOR
select lname, Cargo
from employee
where lname < 'C'
order by 1
OPEN c1
FETCH c1 into @lname, @Cargo
WHILE @@FETCH_STATUS = 0
begin
print @lname + ' ES UN ' + @Cargo
FETCH c1 into @lname, @Cargo
end
CLOSE c1
DEALLOCATE c1

es decir, ¿incluimos tantas columnas como necesitemos en la sentencia
origen
del cursor, y luego obtenemos esos campos asociandolos con variables en la
posicion ordinal correspondiente del FETCH?

Si no, ¿como?

Gracias,

Leonardo
mvp vb

P.S.: La verdad, en este caso concreto, me gusta mas la implementacon en
PL.


Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida