Página 7 de 7
Bien, ahora que ya hemos hecho un proyecto de prueba y sabemos las funciones básicas para interactuar con MySQL desde nuestros programas, vamos a ir creando paso a paso un simple pero funcional sistema de altas y bajas, en el cual estén incluídas todas las operaciones que normalmente realizamos, tales como: búsqueda, inserción, modificación, eliminación.
El código fuente completo del proyecto descárguenlo aquí
Primero vamos a crear una clase que nos permita acceder a una base de datos de MySQL de forma simple, la idea es poder reutilizar esta clase en nuestros proyectos que necesiten acceder a una base de este tipo.
Bien la definición de nuestra clase que permite efectuar operaciones con una base MySQL es:
|
#include <windows.h> #include <mysql/mysql.h> #include <mysql/mysqld_error.h>
class sql_db { private: char *servidor, *usuario, *password, *database; MYSQL *objDatos; public: sql_db(char *servidor, char *usuario, char *password, char *database); ~sql_db(); void sql_close(); MYSQL_RES * ejecutar_sql(char *sql); int numero_filas(MYSQL_RES *res); int filas_afectadas(); int numero_columnas(MYSQL_RES *res); const char *nombre_columna(MYSQL_RES *res, int indice); int longitud_columna(MYSQL_RES *res, int indice); const char *valor_defecto_columna(MYSQL_RES *res, int indice); MYSQL_ROW obtener_fila(MYSQL_RES *res); void fijar_fila(MYSQL_RES *res, int indice); unsigned long ultimo_id(); }; | |
Y la implementación de los métodos es:
sql_db :: sql_db (char *servidor, char *usuario, char *password, char *database)
{
this->servidor = servidor;
this->usuario = usuario;
this->password = password;
this->database = database;
// Intentar iniciar MySQL:
if(!(objDatos = mysql_init(0))) {
// Imposible crear el objeto objDatos
cout << "ERROR: imposible crear el objeto objDatos." << endl;
getchar();
exit(1);
}
// Debe existir un usuario "root" con clave de acceso "clave"
if(!mysql_real_connect(objDatos, this->servidor, this->usuario, this->password, this->database, 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(objDatos) << endl;
mysql_close(objDatos);
rewind(stdin);
getchar();
exit(2);
}
}
sql_db :: ~sql_db()
{
this->sql_close();
}
void sql_db :: sql_close()
{
mysql_close(this->objDatos);
}
MYSQL_RES * sql_db :: ejecutar_sql(char *sql)
{
if(mysql_ping(objDatos)) {
cout << "Error: conexión imposible" << endl;
this->sql_close();
}
if(mysql_query(objDatos, sql)) {
// Error al realizar la consulta:
cout << "ERROR: " << mysql_error(objDatos) << endl;
this->sql_close();
rewind(stdin);
getchar();
exit(2);
}
return mysql_store_result(objDatos);
}
int sql_db :: numero_filas(MYSQL_RES *res)
{
return mysql_num_rows(res);
}
int sql_db :: filas_afectadas()
{
return mysql_affected_rows(this->objDatos);
}
int sql_db :: numero_columnas(MYSQL_RES *res)
{
return mysql_num_fields(res);
}
const char * sql_db :: nombre_columna(MYSQL_RES *res, int indice)
{
return mysql_fetch_field_direct(res, indice)->name;
}
int sql_db :: longitud_columna(MYSQL_RES *res, int indice)
{
return mysql_fetch_field_direct(res, indice)->length;
}
const char * sql_db :: valor_defecto_columna(MYSQL_RES *res, int indice)
{
MYSQL_FIELD *col = mysql_fetch_field_direct(res, indice);
return col->def ? col->def : "NULL";
}
MYSQL_ROW sql_db :: obtener_fila(MYSQL_RES *res)
{
return mysql_fetch_row(res);
}
void sql_db :: fijar_fila(MYSQL_RES *res, int indice)
{
mysql_data_seek(res, indice);
}
unsigned long sql_db :: ultimo_id()
{
return (unsigned long )mysql_insert_id(this->objDatos);
} |
Bien, ahora para continuar diseñemos el program principal.
La definición de la tabla que ya creamos en la parte anterior de este tutorial es:
|
CREATE TABLE personas ( id int(3) NOT NULL auto_increment, nombre varchar(20) default NULL, apellido varchar(20) default NULL, edad int(3) NOT NULL default '0', direccion varchar(40) default NULL, PRIMARY KEY (id) ) AUTO_INCREMENT=1 ; | |
Esta tabla ha sido creada en nuestra base llamada base_ejemplo.
Ahora vamos a crear una estructura de datos para poder representar esta misma tabla, pero en nuestro programa de C/C++, la definición de la estructura es la siguiente:
|
struct persona{ int id; char nombre[20]; char apellido[20]; int edad; char direccion[40]; }; | |
Fíjense que hemos definidos los mismos nombres tanto para los campos en la tabla como para los elementos de la estructura, aunque esto no es necesario.
Lo importante aquí es que los campos de la estructura sean lo más parecidos posible a los campos de la tabla en cuanto a tipos de dato y longitud, es decir si el campo en la tabla es int(3) en nuestra estructura el elemento será int, si en la tabla es varchar(20), en la estructura será char [20] y así sucesivamente.
Para poder trabajar en mejor forma vamos a definir un tipo de dato para nuestra estructura con la línea siguiente:
|
typedef struct persona Persona; | |
Luego vamos a definir un objeto de tipo sql_db en el cual especificamos los parametros de conexion a la base, estos son: servidor, usuario, clave y base inicial:
|
sql_db obj_mysql("localhost", "root", "clave", "base_ejemplo"); | |
Ahora veamos los prototipos de las funciones en nuestro programa:
|
void ingresar(), insertar(Persona info); void buscar(), modificar(), actualizar(Persona info), eliminar(); void ordenar(), mostrar(); char menu(void); void pausa(); | |
Y su implementación es:
void ingresar()
{
Persona info;
cout << "Ingrese nombre: ";
cin >> info.nombre;
cout << "Ingrese apellido: ";
cin >> info.apellido;
cout << "Ingrese edad: ";
cin >> info.edad;
cout << "Ingrese direccion: ";
cin >> info.direccion;
insertar(info);
cout << "Persona ingresada exitosamente" << endl;
}
void insertar(Persona info)
{
char *consulta;
char sentencia[] = "INSERT INTO personas(nombre, apellido, edad, direccion) VALUES('%s', '%s', %d, '%s')";
consulta = new char[strlen(sentencia)+sizeof(Persona)-sizeof(int)];
sprintf(consulta, sentencia, info.nombre, info.apellido, info.edad, info.direccion);
obj_mysql.ejecutar_sql(consulta);
}
void buscar()
{
char nombre[20];
char *consulta;
char sentencia[] = "SELECT * FROM personas WHERE nombre='%s'";
MYSQL_RES *res;
MYSQL_ROW row;
cout << "Ingrese nombre a buscar: ";
cin >> nombre;
consulta = new char[strlen(sentencia)+strlen(nombre)];
sprintf(consulta, sentencia, nombre);
res = obj_mysql.ejecutar_sql(consulta);
if(obj_mysql.filas_afectadas()>0)
{
row = obj_mysql.obtener_fila(res);
cout << "Id: " << row[0] << endl;
cout << "Nombre: " << row[1] << endl;
cout << "Apellido: " << row[2] << endl;
cout << "Edad: " << row[3] << endl;
cout << "Direccion: " << row[4] << endl;
}
else
cout << "Persona no encontrada" << endl;
}
void modificar()
{
char nombre[20];
char *consulta;
char *temp;
char sentencia[] = "SELECT * FROM personas WHERE nombre='%s'";
MYSQL_RES *res;
MYSQL_ROW row;
Persona info;
cout << "Ingrese nombre a modificar: ";
cin >> nombre;
consulta = new char[strlen(sentencia)+strlen(nombre)];
sprintf(consulta, sentencia, nombre);
res = obj_mysql.ejecutar_sql(consulta);
if(obj_mysql.filas_afectadas()>0)
{
row = obj_mysql.obtener_fila(res);
sprintf(temp, "%s", row[0]);
info.id = atoi(temp);
cout << "Ingrese nombre: ";
cin >> info.nombre;
cout << "Ingrese apellido: ";
cin >> info.apellido;
cout << "Ingrese edad: ";
cin >> info.edad;
cout << "Ingrese direccion: ";
cin >> info.direccion;
actualizar(info);
cout << "Datos actualizados exitosamente" << endl;
}
else
cout << "Persona no encontrada" << endl;
}
void actualizar(Persona info)
{
char nombre[20];
char *consulta;
char sentencia[] = "UPDATE personas SET nombre='%s', apellido='%s', edad=%d, direccion='%s' WHERE id=%d";
consulta = new char[strlen(sentencia)+strlen(nombre)];
sprintf(consulta, sentencia, info.nombre, info.apellido, info.edad, info.direccion, info.id);
obj_mysql.ejecutar_sql(consulta);
}
void eliminar()
{
char nombre[20];
char *consulta;
char *temp;
char sentencia_buscar[] = "SELECT * FROM personas WHERE nombre='%s'";
char sentencia_eliminar[] = "DELETE FROM personas WHERE id=%d";
MYSQL_RES *res;
MYSQL_ROW row;
Persona info;
cout << "Ingrese nombre a eliminar: ";
cin >> nombre;
consulta = new char[strlen(sentencia_buscar)+strlen(nombre)];
sprintf(consulta, sentencia_buscar, nombre);
res = obj_mysql.ejecutar_sql(consulta);
if(obj_mysql.filas_afectadas()>0)
{
row = obj_mysql.obtener_fila(res);
sprintf(temp, "%s", row[0]);
int id = atoi(temp);
consulta = new char[strlen(sentencia_eliminar)+sizeof(int)];
sprintf(consulta, sentencia_eliminar, id);
obj_mysql.ejecutar_sql(consulta);
cout << "Datos eliminados exitosamente" << endl;
}
else
cout << "Persona no encontrada" << endl;
}
void ordenar()
{
MYSQL_RES *res;
MYSQL_ROW row;
int filas, columnas;
res = obj_mysql.ejecutar_sql("SELECT * FROM personas ORDER BY nombre");
filas = obj_mysql.numero_filas(res);
columnas = obj_mysql.numero_columnas(res);
cout << "--- Listado de personas (" << filas << ") ---" << endl;
for(int j=0; j < columnas; j++)
cout << obj_mysql.nombre_columna(res, j) << " - ";
cout << endl;
while(row = obj_mysql.obtener_fila(res))
{
for(int j=0; j < columnas; j++)
{
cout << row[j] << ", ";
}
cout << endl;
}
cout << "Se han ordenado los registros por: nombre" << endl;
}
void mostrar()
{
MYSQL_RES *res;
MYSQL_ROW row;
int filas, columnas;
res = obj_mysql.ejecutar_sql("SELECT * FROM personas");
filas = obj_mysql.numero_filas(res);
columnas = obj_mysql.numero_columnas(res);
cout << "--- Listado de personas (" << filas << ") ---" << endl;
for(int j=0; j < columnas; j++)
cout << obj_mysql.nombre_columna(res, j) << " - ";
cout << endl;
while(row = obj_mysql.obtener_fila(res))
{
for(int j=0; j < columnas; j++)
{
cout << row[j] << ", ";
}
cout << endl;
}
}
char menu(void)
{
char c;
cout << "(1)Ingresar, (2)Buscar, (3)Modificar, (4)Eliminar, (5)Ordenar, (6)Mostrar lista, (7)Salir" << endl;
printf("Seleccion: ");
c=getchar();
cout << endl;
return(c);
}
void pausa()
{
cout << endl;
system("PAUSE");
cout << endl;
} |
Por fin la función main, quedará así:
|
int main(int argc, char *argv[]) { system("CLS"); char op;
for( ; ; ) { fflush(stdin); switch(op=menu()) { case '1': ingresar(); pausa(); break; case '2': buscar(); pausa(); break; case '3': modificar(); pausa(); break; case '4': eliminar(); pausa(); break; case '5': ordenar(); pausa(); break; case '6': mostrar(); pausa(); break; case '7': break; default : cout << "Opcion no valida"; pausa(); break; }
if(op=='7') break; system("CLS"); }
return 0; } | |
El código fuente completo del proyecto descárguenlo aquí
Y eso es todo, no damos más explicación para que revisen el código y traten de entenderlo por ustedes mismo, en realidad no es complicado.
|
Comentarios
Justo tuve ese problema, debes de incluir en tu proyecto en la parte de directorios include el include de DEVCPP.
Prueba instalar DEV c++ 4.9. Eso me funcionó
Tengo problemas con el #include de mysql, me dice que no encuentra el archivo ni el directorio y ya hice todo lo que se tenia que hacer.
Espero y puedan ayudarme, gracias.
Suscripción de noticias RSS para comentarios de esta entrada.