Utilizando GetRows

La mayoría de la gente, cuando quiere mostrar datos de una tabla en una página web para, por ejemplo, dibujar una tabla HTML con los resultados de la consulta, utiliza un bucle sencillo para ir imprimiendo, registro a registro… Sin embargo, existe un método mucho menos intenso para el servidor y mucho más rápido. Este artículo explica qué es, cómo y por qué se utiliza GetRows.

Introducción

Seguro que el siguiente fragmento de código te es familiar:

Dim oConn, rs, SQL
SQL="SELECT * FROM Tabla"
set oConn = Server.CreateObject("ADODB.Connection")
oConn.Open "…"
set rs = oConn.Execute(SQL)
Response.Write("<TABLE>")
while not rs.EOF
    Response.Write("<TR>")
    Response.Write("<TD>" & rs.Fields("Nombre") & "</TD>")
    Response.Write("<TD>" & rs.Fields("Fecha") & "</TD>")
    Response.Write("<TD>" & rs.Fields("Numero") & "</TD>")
    Response.Write("</TR>")
    rs.MoveNext
wend
Response.Write("</TABLE>")
rs.Close
set rs = nothing
oConn.Close
set oConn = nothing

Efectivamente, es el típico código para mostrar una tabla en una página ASP. Sin embargo ¿has parado a pensar si este código es eficiente? ¿Cómo se comporta este código cuando es ejecutado?

Os lo voy a explicar. Supongamos una tabla como la anterior, con 3 campos, y 200 registros. ¿Sabes cuántos viajes al servidor tiene que hacer este script?

600 (200 registros x 3 campos)
+200 (por cada rs.MoveNext)
+200 (por cada vez que comprobamos rs.EOF)
======
1000 peticiones para mostrar 200 filas.

De acuerdo, existe la propiedad del objeto Recordset CacheSize, que define cúantos registros se trae ADO del servidor en cada petición. De todas formas, estos viajes, al traer más cantidad de datos, también son más costosos, aunque reducen el stress sobre el servidor.

GetRows

¿Por qué no utilizar GetRows y reducirlo a 1 petición?

Este método del objeto Recordset vuelca el contenido resultante de ejecutar la consulta SQL en un vector bidimensional. Tras ejecutar:

Dim miTabla
miTabla = rs.GetRows

Podemos incluso cerrar y destruir los objetos Recordset y Connection, porque todos los datos están ya en el vector miTabla.

Las ventajas son obvias: nos deshacemos de la relación con el cursor o el Recordset y la base de datos, liberamos mucho antes la memoria para otros scripts y desde luego favorecemos a la base de datos porque la dejamos tranquila mucho antes. 🙂

Aunque suene a broma, este último punto es muy beneficioso para Access, que no soporta especialmente bien muchos usuarios concurrentes.

Una vez volcados los datos, podemos recorrer el vector como hacemos con cualquier otro, imprimirlo, etc. Este vector, como he dicho, tiene dos dimensiones: la primera dimensión corresponde a los campos que tendríamos en rs.Fields y la segunda es el número de registros devueltos.

Así que, para escribir el campo Nombre del primer registro, en el ejemplo anterior, haríamos:

Response.Write miTabla(0,0)

que es el 1er campo (0) de la primera fila(0).

Aquí tenéis el ejemplo anterior, utilizando GetRows:

Dim oConn, rs, SQL, miTabla
Dim I, J
‘Para recorrer el vector
SQL="SELECT * FROM Tabla"
set oConn = Server.CreateObject("ADODB.Connection")
oConn.Open "…"
set rs = oConn.Execute(SQL)
miTabla = rs.GetRows
‘Liberamos los objetos ya!!
rs.Close
set rs = nothing
oConn.Close
set oConn = nothing
Response.Write("<TABLE>")

‘Recorremos el vector
‘Desde el primero hasta el último "registro"…
for I = 0 to UBound(miTabla,2)
    ‘Abrimos una nueva fila
    Response.Write("<TR>")
    ‘Desde el primero hasta el último "campo"…
    for J = 0 to Ubound(miTabla, 1)
        ‘Imprimo una celda para cada campo
        Response.Write("<TD>" & miTabla(J, I) & "</TD>")
    next
Response.Write("</TR>")
next
Response.Write("</TABLE>")

¿Fácil no? Si no estás acostumbrado/a a trabajar con vectores, asegúrate de leer este artículo.

GetRows, además, permite recorrer el conjunto de registros en cualquier orden, ir directamente a uno de ellos, retroceder, avanzar cuatro… sin tener que preocuparnos con los cursores del objeto Recordset.

Otra gran ventaja a favor de GetRows es que contar el número de registros es tan sencillo como:

total = UBound(miTabla,2)+1

Se acabaron los -1 devueltos por RecordCount, o los problemas con "SELECT TOP…"

Para que os hagáis una idea, los Foros de esta web están hechos utilizando exclusivamente GetRows… Es la única forma de avanzar para ver si después hay una respuesta, etc. para ir incluyendo las imágenes que simulan el árbol de mensajes. Hacer eso mismo utilizando métodos de movimiento normales como MoveNext sería imperdonable para la velocidad de la página.

¿Tengo que utilizar números?

Vale, admito que rs.Fields("Nombre") es bastante más descriptivo que miTabla(0, I). Afortunadamente, para cada problema existe una solución, así que vamos a tirar de variables.

Podemos definir los índices del vector con nombres simbólicos si creamos variables con el valor númerico en ellas. En nuestro caso, sabemos que vamos a utilizar Nombre(0), Fecha(1) y Numero(2), así que escribimos:

Dim Nombre
Dim Fecha
Dim Numero
Nombre = 0
Fecha = 1
Numero = 2

y nuestro bucle anterior queda convertido en:


for I = 0 to UBound(miTabla,2)
    ‘Abrimos una nueva fila
    Response.Write("<TR>")
    Response.Write("<TD>" & miTabla(Nombre, I) & "</TD>")   
    Response.Write("<TD>" & miTabla(Fecha, I) & "</TD>")   
    Response.Write("<TD>" & miTabla(Numero, I) & "</TD>")   
    Response.Write("</TR>")
next

Lo cual se parece muchísimo al código al que estamos acostumbrados y es mil veces mejor. El valor de cada índice es sustituido por la variable que contiene ese número y que hemos nombrado de forma que resulte muy explícita. ¡Perfecto!

En resumen…

En fin, espero que este artículo te haya convencido. No necesitas utilizar otra cosa que no sea GetRows nunca más para mostrar datos de base de datos.

P.D: Hay otro método aún más rápido que GetRows… Su nombre es GetString, pero sólo es útil para determinadas tareas, y es el tema de otro artículo… 😉

"Carlos de la Orden es el creador de ASPFácil.com, sitio web dedicado extensivamente al desarrollo de sitios web con Active Server Pages."

Deja un comentario