1.C++连接和操作MySQL的方式
系列文章:
MySQL 设计和命令行模式下建立详解
C++利用MySQL API连接和操作数据库实例详解
在Windows平台,我们可以使用ADO、ODBC或者MySQL API进行连接和操作。ADO (ActiveX Data Objects,ActiveX数据对象)是Microsoft提出的一个用于存取数据源的COM组件。它提供了程序语言和统一数据访问方式OLE DB的一个中间层,也就是Microsoft提出的应用程序接口(API)用以实现访问关系或非关系数据库中的数据。
ODBC(Open DataBase Connection)开放式系统互连,是一种数据库访问协议,提供了访问数据库的API接口。基于ODBC的应用程序,对数据库操作不依赖于具体的DBMS,不直接与DBMS打交道,所有数据库操作由对应DBMS的ODBC驱动程序完成,即:系统中不需要安装DBMS系统,如SQL SERVER 2005,但必须有SQL SERVER 2005的ODBC驱动程序,然后在ODBC管理器中注册数据源后,就可以在应用程序中通过ODBC API访问该数据库。ODBC数据库访问技术只适用于windows系统,因为需要在ODBC驱动程序管理器中进行数据源注册,而只有windows才集成了ODBC驱动程序管理器(“控制面板/管理工具/数据源”)。
ADO具有跨系统平台特性,它直接对DBMS数据库进行操作,即系统中必须有DBMS,但不需要驱动程序,不需要注册数据源,所以具有很好的可移植性。
那么,在Linux平台如何连接和使用MSQL数据库呢?我们同样可以使用ADO、unixODBC或者MySQL API。这里不再赘述前两者的用法,读者可自行研究实践,下文将详细讲解MySQL创建数据库和C++利用MSQL API连接和操作数据库。
2.MSQL数据库的设计和建立
MySQL数据库管理系统(DBMS)中,包含的MySQL中定义数据字段的类型对你数据库的优化是非常重要的。MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。
本文以大学熟悉的学生选课管理系统中用到的数据库为例,来实现对数据库的访问。本文数据库的建立,是在Linux平台使用msyql命令完成
主要有三张表:学生表,课程表和选课表。下面是数据表的详细情况。
学生表:

课程表:

选课表:

3.MSQL数据库的连接和操作
下面将讲解利用MySQL API来编写我们自己的用于访问MySQL的中间件,也是我们自己的组件。我们的组件在应用程序和MySQL数据库之间构成的层次结构如下图所示:

下面就来设计和实现我们自己的C++访问MySQL数据库的组件。
3.1头文件的设计
//mysqlhelper.h
#ifndef __MYSQL_HELPER_H__
#define __MYSQL_HELPER_H__
#include <stdlib.h>
#include <map>
#include <vector>
#include <string>
using namespace std;
#include <mysql.h>
namespace mysqlhelper
{
/*********************
*@brief 数据库异常类
**********************/
struct MysqlHelper_Exception //: public TC_Exception
{
MysqlHelper_Exception(const string &sBuffer):errorInfo(sBuffer){}; //: TC_Exception(sBuffer){};
~MysqlHelper_Exception() throw(){};
string errorInfo;
};
/***********************
* @brief 数据库配置接口
***********************/
struct DBConf
{
string _host;//主机地址
string _user; //用户名
string _password;//密码
string _database; //数据库
string _charset; //字符集
int _port;//端口
int _flag; //客户端标识
/*****************
* @brief 构造函数
*****************/
DBConf():_port(0), _flag(0){}
/**********************************
* @brief 读取数据库配置.
* @param mpParam 存放数据库配置的map
* dbhost: 主机地址
* dbuser:用户名
* dbpass:密码
* dbname:数据库名称
* dbport:端口
**********************************/
void loadFromMap(const map<string, string> &mpParam)
{
map<string, string> mpTmp = mpParam;
_host = mpTmp["dbhost"];
_user = mpTmp["dbuser"];
_password = mpTmp["dbpass"];
_database = mpTmp["dbname"];
_charset = mpTmp["charset"];
_port = atoi(mpTmp["dbport"].c_str());
_flag = 0;
if(mpTmp["dbport"] == "")
{
_port = 3306;
}
}
};
/**************************************************************
* @brief:MySQL数据库操作类
* @feature:非线程安全,通常一个线程一个MysqlHelper对象;
* 对于insert/update可以有更好的函数封装,保证SQL注入;
* MysqlHelper::DB_INT表示组装sql语句时,不加””和转义;
* MysqlHelper::DB_STR表示组装sql语句时,加””并转义;
**************************************************************/
class MysqlHelper{
public:
/**
* @brief 构造函数
*/
MysqlHelper();
/**
* @brief 构造函数.
* @param: sHost:主机IP
* @param sUser 用户
* @param sPasswd 密码
* @param sDatebase 数据库
* @param port 端口
* @param iUnixSocket socket
* @param iFlag 客户端标识
*/
MysqlHelper(const string& sHost, const string& sUser = "", const string& sPasswd = "", const string& sDatabase = "", const string &sCharSet = "", int port = 0, int iFlag = 0);
/**
* @brief 构造函数.
* @param tcDBConf 数据库配置
*/
MysqlHelper(const DBConf& tcDBConf);
/**
* @brief 析构函数.
*/
~MysqlHelper();
/**
* @brief 初始化.
*
* @param sHost 主机IP
* @param sUser 用户
* @param sPasswd 密码
* @param sDatebase 数据库
* @param port 端口
* @param iUnixSocket socket
* @param iFlag 客户端标识
* @return 无
*/
void init(const string& sHost, const string& sUser = "", const string& sPasswd = "", const string& sDatabase = "", const string &sCharSet = "", int port = 0, int iFlag = 0);
/**
* @brief 初始化.
*
* @param tcDBConf 数据库配置
*/
void init(const DBConf& tcDBConf);
/**
* @brief 连接数据库.
*
* @throws MysqlHelper_Exception
* @return 无
*/
void connect();
/**
* @brief 断开数据库连接.
* @return 无
*/
void disconnect();
/**
* @brief 获取数据库变量.
* @return 数据库变量
*/
string getVariables(const string &sName);
/**
* @brief 直接获取数据库指针.
*
* @return MYSQL* 数据库指针
*/
MYSQL *getMysql();
/**
* @brief 字符转义.
*
* @param sFrom 源字符串
* @param sTo 输出字符串
* @return 输出字符串
*/
string escapeString(const string& sFrom);
/**
* @brief 更新或者插入数据.
*
* @param sSql sql语句
* @throws MysqlHelper_Exception
* @return
*/
void execute(const string& sSql);
/**
* @brief mysql的一条记录
*/
class MysqlRecord
{
public:
/**
* @brief 构造函数.
*
* @param record
*/
MysqlRecord(const map<string, string> &record);
/**
* @brief 获取数据,s一般是指数据表的某个字段名
* @param s 要获取的字段
* @return 符合查询条件的记录的s字段名
*/
const string& operator[](const string &s);
protected:
const map<string, string> &_record;
};
/**
* @brief 查询出来的mysql数据
*/
class MysqlData
{
public:
/**
* @brief 所有数据.
*
* @return vector<map<string,string>>&
*/
vector<map<string, string> >& data();
/**
* 数据的记录条数
*
* @return size_t
*/
size_t size();
/**
* @brief 获取某一条记录.
*
* @param i 要获取第几条记录
* @return MysqlRecord类型的数据,可以根据字段获取相关信息,
*/
MysqlRecord operator[](size_t i);
protected:
vector<map<string, string> > _data;
};
/**
* @brief Query Record.
*
* @param sSql sql语句
* @throws MysqlHelper_Exception
* @return MysqlData类型的数据,可以根据字段获取相关信息
*/
MysqlData queryRecord(const string& sSql);
/**
* @brief 定义字段类型,
* DB_INT:数字类型
* DB_STR:字符串类型
*/
enum FT
{
DB_INT,
DB_STR,
};
/**
* 数据记录
*/
typedef map<string, pair<FT, string> > RECORD_DATA;
/**
* @brief 更新记录.
*
* @param sTableName 表名
* @param m

