Trabajar con conjuntos de resultados muy grandes

Si el conjunto de resultados contiene muchas filas puede ser poco práctico usar la función mysql_store_result, ya que se requerirá mucha memoria para almacenar el conjunto completo, posiblemente más de la disponible.

Cuando eso suceda, o cuando preveamos que esa situación puede suceder, podemos usar la función mysql_use_result en su lugar.

Esta función no carga el conjunto de resultados en memoria, y se usa la función mysql_fetch_row para recuperar las filas una por una.

MySQL recomienda no realizar procesos muy largos con cada fila, ya que la tabla está bloqueada para otros usuarios hasta que se llame a mysql_free_result.

   // El mismo proceso usando mysql_use_result:
   // Hacer una consulta con el comando "SELECT * FROM gente":
   if(mysql_query(myData, "SELECT * FROM gente")) \{
      // Error al realizar la consulta:
      cout << "ERROR: " << mysql_error(myData) << endl;
      mysql_close(myData);
      return 2;
   }
   if((res = mysql_use_result(myData))) \{
      j = (int) mysql_num_fields(res);
      while(row = mysql_fetch_row(res)) \{
         for(k = 0 ; k < j ; k++)
            cout << ((row[k]==NULL) ? "NULL" : row[k]) << endl;
      }

      // Liberar el resultado de la consulta:
      mysql_free_result(res);
   }

En este ejemplo hacemos uso del hecho de que el valor de retorno de mysql_fetch_row es NULL si no quedan filas por leer. No tenemos otra opción, ya que la función mysql_num_rows no funcionará correctamente hasta que se terminen de procesar todas las filas.

Las funciones mysql_data_seek, mysql_row_seek y mysql_row_tell no se pueden usar cuando se recupera un conjunto de resultados con la función mysql_use_result.

Ejemplo

Veamos un ejemplo completo en el que se aplican estas funciones.

/*
  Name: MySQL Ejemplo 1
  Author: Salvador Pozo Coronado, salvador@conclase.net
  Date: 07/05/2005
  Description: Ejemplo para mostrar contenidos de bases de datos
  usando MySQL.
  Nota: incluir la opción "-lmysql" en las opciones del linker
  dentro de las opciones de proyecto.
*/

// Includes...
#include <iostream>
#include <windows.h>
#include <mysql/mysql.h>
#include <mysql/mysqld_error.h>
#include <cstring>
#include <cstdio>

using namespace std;

// Programa principal
int main()
\{
   // Variables
   MYSQL           *myData;
   MYSQL_RES       *res;
   MYSQL_ROW        row;
   MYSQL_FIELD     *columna;
   int              i, j, k, l;
   unsigned long   *lon;
   MYSQL_ROW_OFFSET pos;

   // Intentar iniciar MySQL:
   if(!(myData = mysql_init(0))) \{
      // Imposible crear el objeto myData
      cout << "ERROR: imposible crear el objeto myData." << endl;
      rewind(stdin);
      getchar();
      return 1;
   }

   // Debe existir un usuario "curso" con clave de acceso "clave" y
   // con al menos el privilegio "SELECT" sobre la tabla
   // "prueba.gente"
   if(!mysql_real_connect(myData, NULL, "curso", "clave", "prueba", MYSQL_PORT, NULL, 0)) \{
      // No se puede conectar con el servidor en el puerto especificado.
      cout << "Imposible conectar con servidor mysql en el puerto " 
           << MYSQL_PORT << " Error: " << mysql_error(myData) << endl;
      mysql_close(myData);
      rewind(stdin);
      getchar();
      return 1;
   }

   // Conectar a base de datos.
   if(mysql_select_db(myData, "prueba")) \{
      // Imposible seleccionar la base de datos, posiblemente no existe.
      cout << "ERROR: " << mysql_error(myData) << endl;
      mysql_close(myData);
      rewind(stdin);
      getchar();
      return 2;
   }
 
   // Hacer una consulta con el comando "SELECT * FROM gente":
   if(mysql_query(myData, "SELECT * FROM gente")) \{
      // Error al realizar la consulta:
      cout << "ERROR: " << mysql_error(myData) << endl;
      mysql_close(myData);
      rewind(stdin);
      getchar();
      return 2;
   }

   // Almacenar el resultado de la consulta:
   if((res = mysql_store_result(myData))) \{
      // Obtener el número de registros seleccionados:
      i = (int) mysql_num_rows(res);
      // Obtener el número de columnsa por fila:
      j = (int) mysql_num_fields(res);

      // Mostrar el número de registros seleccionados:
      cout << "Consulta:  SELECT * FROM gente" << endl;
      cout << "Numero de filas encontradas:  " << i << endl;
      cout << "Numero de columnas por fila:  " << j << endl;
  
      // Información sobre columnas usando mysql_fetch_field:
      cout << endl << "Informacion sobre columnas:" << endl;
      for(l = 0; l < j; l++) \{
         columna = mysql_fetch_field(res);
         cout << "Nombre: " << columna->name << endl;
         cout << "Longitud: " << columna->length << endl;
         cout << "Valor por defecto: " << (columna->def ? columna->def : "NULL") << endl;
      }
      cout << endl;

      // Información sobre columnas usando mysql_fetch_fields:
      cout << endl << "Informacion sobre columnas:" << endl;
      columna = mysql_fetch_fields(res);
      for(l = 0; l < j; l++) \{
         cout << "Nombre: " << columna[l].name << endl;
         cout << "Longitud: " << columna[l].length << endl;
         cout << "Valor por defecto: " << (columna[l].def ? columna[l].def : "NULL") << endl;
      }
      cout << endl;

      // Información sobre columnas n, usando mysql_fetch_field_direct:
      cout << endl << "Informacion sobre columna 1:" << endl;
      columna = mysql_fetch_field_direct(res, 1);
      cout << "Nombre: " << columna->name << endl;
      cout << "Longitud: " << columna->length << endl;
      cout << "Valor por defecto: " << (columna->def ? columna->def : "NULL") << endl;
      cout << endl;

      // Leer registro a registro y mostrar:
      l=1;
      for(l = 0; l < i; l++) \{
         row = mysql_fetch_row(res);
         lon = mysql_fetch_lengths(res);
         cout << "Registro no. " << l+1 << endl;
         // Mostrar cada campo y su longitud:
         for(k = 0 ; k < j ; k++) \{
            cout << ((row[k]==NULL) ? "NULL" : row[k]);
            cout << " longitud: " << lon[k] << endl;
         }
      }
      
      cout << endl;
      
      // Mostrar sólo 3ª fila:
      mysql_data_seek(res, 2);
      row = mysql_fetch_row(res);
      cout << "Tercera fila" << endl;
      for(k = 0 ; k < j ; k++) \{
         cout << ((row[k]==NULL) ? "NULL" : row[k]) << endl;
      }

      // Almacenar posición de la fila actual (la 4ª):
      pos = mysql_row_tell(res);
      // Lectura de filas hasta el final:
      while(mysql_fetch_row(res));
      // Recuperar la posición guardada:
      mysql_row_seek(res, pos);
      row = mysql_fetch_row(res);
      cout << "Cuarta fila" << endl;
      for(k = 0 ; k < j ; k++) \{
         cout << ((row[k]==NULL) ? "NULL" : row[k]) << endl;
      }

      cout << endl;

      // Liberar el resultado de la consulta:
      mysql_free_result(res);
   }
   
   // El mismo proceso usando mysql_use_result:
   // Hacer una consulta con el comando "SELECT * FROM gente":
   if(mysql_query(myData, "SELECT * FROM gente")) \{
      // Error al realizar la consulta:
      cout << "ERROR: " << mysql_error(myData) << endl;
      mysql_close(myData);
      rewind(stdin);
      getchar();
      return 2;
   }
   
   // Mostrar todas las filas:
   if((res = mysql_use_result(myData))) \{
      j = (int) mysql_num_fields(res);
      while(row = mysql_fetch_row(res)) \{
         for(k = 0 ; k < j ; k++)
            cout << ((row[k]==NULL) ? "NULL" : row[k]) << endl;
      }

      // Liberar el resultado de la consulta:
      mysql_free_result(res);
   }
   // Cerrar la conexión
   mysql_close(myData);
    
   // Esperar a que se pulse una tecla y salir.
   rewind(stdin);
   getchar();
   return 0;
}

Comentarios de los usuarios (1)

Dante
2011-05-19 06:47:11

estimados c con clase, agradesco sus atribuciones en este lenguaje de c++ con tutoriales, estuve viendo este de c++ con mysql y al querer hacer una prueba de lo que estaba aprendiendo, trate de ejecutar el ejemplo que ponen de consultas, y a la hora de compilar me salen 34 errores, quisiera aprender a enlazar mysql con c++, pero aun no he visto un solo ejemplo que se ejecute con precicion y que demuestre que lo que hago es correcto. Gracias por su atencion.