C++利用MySQL API连接和操作数据库实例详解

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 mpColumns 列名/值对
 * @param sCondition where子语句,例如:where A = B
 * @throws MysqlHelper_Exception
 * @return size_t 影响的行数
 */
 size_t updateRecord(const string &sTableName, const map<string, pair<FT, string> > &mpColumns, const string &sCondition);

 /**
 * @brief 插入记录.
 *
 * @param sTableName 表名
 * @param mpColumns 列名/值对
 * @throws MysqlHelper_Exception
 * @return size_t 影响的行数
 */
 size_t insertRecord(const string &sTableName, const map<string, pair<FT, string> > &mpColumns);

 /**
 * @brief 替换记录.
 *
 * @param sTableName 表名
 * @param mpColumns 列名/值对
 * @throws MysqlHelper_Exception
 * @return size_t 影响的行数
 */
 size_t replaceRecord(const string &sTableName, const map<string, pair<FT, string> > &mpColumns);

 /**
 * @brief 删除记录.
 *
 * @param sTableName 表名
 * @param sCondition where子语句,例如:where A = B
 * @throws MysqlHelper_Exception
 * @return size_t 影响的行数
 */
 size_t deleteRecord(const string &sTableName, const string &sCondition = "");

 /**
 * @brief 获取Table查询结果的数目.
 *
 * @param sTableName 用于查询的表名
 * @param sCondition where子语句,例如:where A = B
 * @throws MysqlHelper_Exception
 * @return size_t 查询的记录数目
 */
 size_t getRecordCount(const string& sTableName, const string &sCondition = "");

 /**
 * @brief 获取Sql返回结果集的个数.
 *
 * @param sCondition where子语句,例如:where A = B
 * @throws MysqlHelper_Exception
 * @return 查询的记录数目
 */
 size_t getSqlCount(const string &sCondition = "");

 /**
 * @brief 存在记录.
 *
 * @param sql sql语句
 * @throws MysqlHelper_Exception
 * @return 操作是否成功
 */
 bool existRecord(const string& sql);

 /**
 * @brief 获取字段最大值.
 *
 * @param sTableName 用于查询的表名
 * @param sFieldName 用于查询的字段
 * @param sCondition where子语句,例如:where A = B
 * @throws MysqlHelper_Exception
 * @return 查询的记录数目
 */
 int getMaxValue(const string& sTableName, const string& sFieldName, const string &sCondition = "");

 /**
 * @brief 获取auto_increment最后插入得ID.
 *
 * @return ID值
 */
 long lastInsertID();

 /**
 * @brief 构造Insert-SQL语句.
 *
 * @param sTableName 表名
 * @param mpColumns 列名/值对
 * @return string insert-SQL语句
 */
 string buildInsertSQL(const string &sTableName, const map<string, pair<FT, string> > &mpColumns);

 /**
 * @brief 构造Replace-SQL语句.
 *
 * @param sTableName 表名
 * @param mpColumns 列名/值对
 * @return string insert-SQL语句
 */
 string buildReplaceSQL(const string &sTableName, const map<string, pair<FT, string> > &mpColumns);

 /**
 * @brief 构造Update-SQL语句.
 *
 * @param sTableName 表名
 * @param mpColumns 列名/值对
 * @param sCondition where子语句
 * @return string Update-SQL语句
 */
 string buildUpdateSQL(const string &sTableName,const map<string, pair<FT, string> > &mpColumns, const string &sCondition);

 /**
 * @brief 获取最后执行的SQL语句.
 *
 * @return SQL语句
 */
 string getLastSQL() { return _sLastSql; }

 /**
 * @brief 获取查询影响数
 * @return int
 */
 size_t getAffectedRows();
protected:
 /**
 * @brief copy contructor,只申明,不定义,保证不被使用
 */
 MysqlHelper(const MysqlHelper &tcMysql);

 /**
 *
 * @brief 只申明,不定义,保证不被使用
 */
 MysqlHelper &operator=(const MysqlHelper &tcMysql);

private:

 /**
 * 数据库指针
 */
 MYSQL *_pstMql;

 /**
 * 数据库配置
 */
 DBConf _dbConf;

 /**
 * 是否已经连接
 */
 bool _bConnected;

 /**
 * 最后执行的sql
 */
 string _sLastSql;

};
}
#endif //__MYSQL_HELPER_H__

3.2源文件具体实现

//mysqlhelper.cpp

#include "mysqlHelper.h"

#include <string.h>
#include <sstream>

using namespace std;

namespace mysqlhelper{

MysqlHelper::MysqlHelper():_bConnected(false)
{
 _pstMql = mysql_init(NULL);
}

MysqlHelper::MysqlHelper(const string& sHost, const string& sUser, const string& sPasswd, const string& sDatabase, const string &sCharSet, int port, int iFlag)
:_bConnected(false)
{
 init(sHost, sUser, sPasswd, sDatabase, sCharSet, port, iFlag);

 _pstMql = mysql_init(NULL);
}

MysqlHelper::MysqlHelper(const DBConf& tcDBConf)
:_bConnected(false)
{
 _dbConf = tcDBConf;

 _pstMql = mysql_init(NULL);
}

MysqlHelper::~MysqlHelper()
{
 if (_pstMql != NULL)
 {
 mysql_close(_pstMql);
 _pstMql = NULL;
 }
}

void MysqlHelper::init(const string& sHost, const string& sUser, const string& sPasswd, const string& sDatabase, const string &sCharSet, int port, int iFlag)
{
 _dbConf._host = sHost;
 _dbConf._user = sUser;
 _dbConf._password = sPasswd;
 _dbConf._database = sDatabase;
 _dbConf._charset = sCharSet;
 _dbConf._port = port;
 _dbConf._flag = iFlag;
}

void MysqlHelper::init(const DBConf& tcDBConf)
{
 _dbConf = tcDBConf;
}

void MysqlHelper::connect()
{
 disconnect();

 if( _pstMql == NULL)
 {
 _pstMql = mysql_init(NULL);
 }

 //建立连接后, 自动调用设置字符集语句
 if(!_dbConf._charset.empty()) {
 if (mysql_options(_pstMql, MYSQL_SET_CHARSET_NAME, _dbConf._charset.c_str())) {
 throw MysqlHelper_Exception(string("MysqlHelper::connect: mysql_options MYSQL_SET_CHARSET_NAME ") + _dbConf._charset + ":" + string(mysql_error(_pstMql)));
 }
 }

 if (mysql_real_connect(_pstMql, _dbConf._host.c_str(), _dbConf._user.c_str(), _dbConf._password.c_str(), _dbConf._database.c_str(), _dbConf._port, NULL, _dbConf._flag) == NULL)
 {
 throw MysqlHelper_Exception("[MysqlHelper::connect]: mysql_real_connect: " + string(mysql_error(_pstMql)));
 }

 _bConnected = true;
}

void MysqlHelper::disconnect()
{
 if (_pstMql != NULL)
 {
 mysql_close(_pstMql);
 _pstMql = mysql_init(NULL);
 }

 _bConnected = false;
}

string MysqlHelper::escapeString(const string& sFrom)
{
 if(!_bConnected)
 {
 connect();
 }

 string sTo;
 string::size_type iLen = sFrom.length() * 2 + 1;
 char *pTo = (char *)malloc(iLen);

 memset(pTo, 0x00, iLen);

 mysql_real_escape_string(_pstMql, pTo, sFrom.c_str(), sFrom.length());

 sTo = pTo;

 free(pTo);

 return sTo;
}

MYSQL *MysqlHelper::getMysql(void)
{
 return _pstMql;
}

string MysqlHelper::buildInsertSQL(const string &sTableName, const RECORD_DATA &mpColumns)
{
 ostringstream sColumnNames;
 ostringstream sColumnValues;

 map<string, pair<FT, string> >::const_iterator itEnd = mpColumns.end();

 for(map<string, pair<FT, string> >::const_iterator it = mpColumns.begin(); it != itEnd; ++it)
 {
 if (it == mpColumns.begin())
 {
 sColumnNames << "`" << it->first << "`";
 if(it->second.first == DB_INT)
 {
 sColumnValues << it->second.second;
 }
 else
 {
 sColumnValues << "'" << escapeString(it->second.second) << "'";
 }
 }
 else
 {
 sColumnNames << ",`" << it->first << "`";
 if(it->second.first == DB_INT)
 {
 sColumnValues << "," + it->second.second;
 }
 else
 {
 sColumnValues << ",'" + escapeString(it->second.second) << "'";
 }
 }
 }

 ostringstream os;
 os << "insert into " << sTableName << " (" << sColumnNames.str() << ") values (" << sColumnValues.str() << ")";
 return os.str();
}

string MysqlHelper::buildReplaceSQL(const string &sTableName, const RECORD_DATA &mpColumns)
{
 ostringstream sColumnNames;
 ostringstream sColumnValues;

 map<string, pair<FT, string> >::const_iterator itEnd = mpColumns.end();
 for(map<string, pair<FT, string> >::const_iterator it = mpColumns.begin(); it != itEnd; ++it)
 {
 if (it == mpColumns.begin())
 {
 sColumnNames << "`" << it->first << "`";
 if(it->second.first == DB_INT)
 {
 sColumnValues << it->second.second;
 }
 else
 {
 sColumnValues << "'" << escapeString(it->second.second) << "'";
 }
 }
 else
 {
 sColumnNames << ",`" << it->first << "`";
 if(it->second.first == DB_INT)
 {
 sColumnValues << "," + it->second.second;
 }
 else
 {
 sColumnValues << ",'" << escapeString(it->second.second) << "'";
 }
 }
 }

 ostringstream os;
 os << "replace into " << sTableName << " (" << sColumnNames.str() << ") values (" << sColumnValues.str() << ")";
 return os.str();
}

string MysqlHelper::buildUpdateSQL(const string &sTableName,const RECORD_DATA &mpColumns, const string &sWhereFilter)
{
 ostringstream sColumnNameValueSet;

 map<string, pair<FT, string> >::const_iterator itEnd = mpColumns.end();

 for(map<string, pair<FT, string> >::const_iterator it = mpColumns.begin(); it != itEnd; ++it)
 {
 if (it == mpColumns.begin())
 {
 sColumnNameValueSet << "`" << it->first << "`";
 }
 else
 {
 sColumnNameValueSet << ",`" << it->first << "`";
 }

 if(it->second.first == DB_INT)
 {
 sColumnNameValueSet << "= " << it->second.second;
 }
 else
 {
 sColumnNameValueSet << "= '" << escapeString(it->second.second) << "'";
 }
 }

 ostringstream os;
 os << "update " << sTableName << " set " << sColumnNameValueSet.str() << " " << sWhereFilter;

 return os.str();
}

string MysqlHelper::getVariables(const string &sName)
{
 string sql = "SHOW VARIABLES LIKE '" + sName + "'";

 MysqlData data = queryRecord(sql);
 if(data.size() == 0)
 {
 return "";
 }

 if(sName == data[0]["Variable_name"])
 {
 return data[0]["Value"];
 }

 return "";
}

void MysqlHelper::execute(const string& sSql)
{
 /**
 没有连上, 连接数据库
 */
 if(!_bConnected)
 {
 connect();
 }

 _sLastSql = sSql;

 int iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
 if(iRet != 0)
 {
 /**
 自动重新连接
 */
 int iErrno = mysql_errno(_pstMql);
 if (iErrno == 2013 || iErrno == 2006)
 {
 connect();
 iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
 }
 }

 if (iRet != 0)
 {
 throw MysqlHelper_Exception("[MysqlHelper::execute]: mysql_query: [ " + sSql+" ] :" + string(mysql_error(_pstMql)));
 }
}

MysqlHelper::MysqlData MysqlHelper::queryRecord(const string& sSql)
{
 MysqlData data;

 /**
 没有连上, 连接数据库
 */
 if(!_bConnected)
 {
 connect();
 }

 _sLastSql = sSql;

 int iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
 if(iRet != 0)
 {
 /**
 自动重新连接
 */
 int iErrno = mysql_errno(_pstMql);
 if (iErrno == 2013 || iErrno == 2006)
 {
 connect();
 iRet = mysql_real_query(_pstMql, sSql.c_str(), sSql.length());
 }
 }

 if (iRet != 0)
 {
 throw MysqlHelper_Exception("[MysqlHelper::execute]: mysql_query: [ " + sSql+" ] :" + string(mysql_error(_pstMql)));
 }

 MYSQL_RES *pstRes = mysql_store_result(_pstMql);

 if(pstRes == NULL)
 {
 throw MysqlHelper_Exception("[MysqlHelper::queryRecord]: mysql_store_result: " + sSql + " : " + string(mysql_error(_pstMql)));
 }

 vector<string> vtFields;
 MYSQL_FIELD *field;
 while((field = mysql_fetch_field(pstRes)))
 {
 vtFields.push_back(field->name);
 }

 map<string, string> mpRow;
 MYSQL_ROW stRow;

 while((stRow = mysql_fetch_row(pstRes)) != (MYSQL_ROW)NULL)
 {
 mpRow.clear();
 unsigned long * lengths = mysql_fetch_lengths(pstRes);
 for(size_t i = 0; i < vtFields.size(); i++)
 {
 if(stRow[i])
 {
 mpRow[vtFields[i]] = string(stRow[i], lengths[i]);
 }
 else
 {
 mpRow[vtFields[i]] = "";
 }
 }

 data.data().push_back(mpRow);
 }

 mysql_free_result(pstRes);

 return data;
}

size_t MysqlHelper::updateRecord(const string &sTableName, const RECORD_DATA &mpColumns, const string &sCondition)
{
 string sSql = buildUpdateSQL(sTableName, mpColumns, sCondition);
 execute(sSql);

 return mysql_affected_rows(_pstMql);
}

size_t MysqlHelper::insertRecord(const string &sTableName, const RECORD_DATA &mpColumns)
{
 string sSql = buildInsertSQL(sTableName, mpColumns);
 execute(sSql);

 return mysql_affected_rows(_pstMql);
}

size_t MysqlHelper::replaceRecord(const string &sTableName, const RECORD_DATA &mpColumns)
{
 string sSql = buildReplaceSQL(sTableName, mpColumns);
 execute(sSql);

 return mysql_affected_rows(_pstMql);
}

size_t MysqlHelper::deleteRecord(const string &sTableName, const string &sCondition)
{
 ostringstream sSql;
 sSql << "delete from " << sTableName << " " << sCondition;

 execute(sSql.str());

 return mysql_affected_rows(_pstMql);
}

size_t MysqlHelper::getRecordCount(const string& sTableName, const string &sCondition)
{
 ostringstream sSql;
 sSql << "select count(*) as num from " << sTableName << " " << sCondition;

 MysqlData data = queryRecord(sSql.str());

 long n = atol(data[0]["num"].c_str());

 return n;

}

size_t MysqlHelper::getSqlCount(const string &sCondition)
{
 ostringstream sSql;
 sSql << "select count(*) as num " << sCondition;

 MysqlData data = queryRecord(sSql.str());

 long n = atol(data[0]["num"].c_str());

 return n;
}

int MysqlHelper::getMaxValue(const string& sTableName, const string& sFieldName,const string &sCondition)
{
 ostringstream sSql;
 sSql << "select " << sFieldName << " as f from " << sTableName << " " << sCondition << " order by f desc limit 1";

 MysqlData data = queryRecord(sSql.str());

 int n = 0;

 if(data.size() == 0)
 {
 n = 0;
 }
 else
 {
 n = atol(data[0]["f"].c_str());
 }

 return n;
}

bool MysqlHelper::existRecord(const string& sql)
{
 return queryRecord(sql).size() > 0;
}

long MysqlHelper::lastInsertID()
{
 return mysql_insert_id(_pstMql);
}

size_t MysqlHelper::getAffectedRows()
{
 return mysql_affected_rows(_pstMql);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
MysqlHelper::MysqlRecord::MysqlRecord(const map<string, string> &record):_record(record){}

const string& MysqlHelper::MysqlRecord::operator[](const string &s)
{
 map<string, string>::const_iterator it = _record.find(s);
 if(it == _record.end())
 {
 throw MysqlHelper_Exception("field '" + s + "' not exists.");
 }
 return it->second;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

vector<map<string, string> >& MysqlHelper::MysqlData::data()
{
 return _data;
}

size_t MysqlHelper::MysqlData::size()
{
 return _data.size();
}

MysqlHelper::MysqlRecord MysqlHelper::MysqlData::operator[](size_t i)
{
 return MysqlRecord(_data[i]);
}

}//end namespace 

3.3使用demo

/****************************************************
*@brief:mysqlhelper demo
*@autor:lvlv
*@date:2016.06.12
*@MySQL version:MySQL Community Server 5.6.30 (GPL)
****************************************************/

#include <string.h>
#include <iostream>
#include <string>
using namespace std;

#include "mysqlHelper.h"
using namespace mysqlhelper;

int main(int argc,char* argv[]){

 //初始化mysql对象并建立连接
 MysqlHelper mysqlHelper;
 mysqlHelper.init("119.29.184.114","root","123456","StudentCourse");
 try{
 mysqlHelper.connect();
 }catch(MysqlHelper_Exception& excep){
 cout<<excep.errorInfo;
 return -1;
 }

 //增加一条学生记录
 //示例插入语句
 //string sql="insert into student values("201421031060","吕吕","华南理工大学","2014","软件工程",1)";

 MysqlHelper::RECORD_DATA record;
 record.insert(make_pair("studentNo",make_pair(MysqlHelper::DB_STR,"201421031060")));
 record.insert(make_pair("name",make_pair(MysqlHelper::DB_STR,"吕吕")));
 record.insert(make_pair("school",make_pair(MysqlHelper::DB_STR,"广州中医药大学")));
 record.insert(make_pair("grade",make_pair(MysqlHelper::DB_STR,"2014")));
 record.insert(make_pair("major",make_pair(MysqlHelper::DB_STR,"计算机科学与技术")));
 record.insert(make_pair("gender",make_pair(MysqlHelper::DB_INT,"1")));
 int res=0;
 try{
 res=mysqlHelper.insertRecord("student",record);
 }catch(MysqlHelper_Exception& excep){
 cout<<excep.errorInfo;
 return -1;
 }
 cout<<"res:"<<res<<" insert successfully "<<endl;

 //删除一条学生记录,学号为201421031059
 try{
 res=mysqlHelper.deleteRecord("student","where studentNo=\"201421031059\"");
 }catch(MysqlHelper_Exception& excep){
 cout<<excep.errorInfo;
 return -1;
 }
 cout<<"res:"<<res<<" delete successfully "<<endl;

 //查找学号为201421031059的学生选择的所有课程名称
 MysqlHelper::MysqlData dataSet;
 string querySQL="select courseName from course co where co.courseNo in (select courseNo from courseSelection where studentNo=\"201421031060\")";
 try{
 dataSet=mysqlHelper.queryRecord(querySQL);
 }catch(MysqlHelper_Exception& excep){
 cout<<excep.errorInfo;
 return -1;
 }
 cout<<"query successfully"<<endl;
 for(size_t i=0;i<dataSet.size();++i){
 cout<<dataSet[i]["courseName"]<<endl;
 }

 //修改学号为201421031060的学生专业
 MysqlHelper::RECORD_DATA recordChange;
 recordChange.insert(make_pair("major",make_pair(MysqlHelper::DB_STR,"软件工程")));
 try{
 res=mysqlHelper.updateRecord("student",recordChange,"where studentNo=\"201421031060\"");
 }catch(MysqlHelper_Exception& excep){
 cout<<excep.errorInfo;
 return -1;
 }
 cout<<"res:"<<res<<" update successfully"<<endl;

 return 0;
}

3.4makefile

##################################
# @brief:make scripts
# @date:2016.05.28
# @author:lvlv
##################################

#environment var
VPATH+=.

CC:=g++
FLAGS=-g -Wall -std=c++11
INC+=-I/usr/local/mysql/include
LIBDIR+=-L/usr/local/mysql/lib

CPPDIRS=.
CPPS=$(shell for dir in ${CPPDIRS};do echo $${dir}/*.cpp;done)

OBJDIR=obj
OBJS=$(patsubst %.cpp,${OBJDIR}/%.o,$(notdir ${CPPS}))

TARGET:=mysqlDemo.out

${TARGET}:${OBJS}
 ${CC} ${FLAGS} ${OBJS} -o $@ ${LIBDIR} -lmysqlclient

${OBJDIR}/%.o:./%.cpp
 ${CC} ${FLAGS} ${INC} -o $@ -c $<

.PHONY:clean
clean:
 rm -f ${TARGET} ${OBJDIR}/*

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Linux下实现C++操作Mysql数据库

    想用C++写项目,数据库是必须的,所以这两天学了一下C++操作MySQL数据库的方法.也没有什么教程,就是在网上搜的知识,下面汇总一下. 连接MySQL数据库有两种方法:第一种是使用ADO连接,不过这种只适合Windows平台:第二种是使用MySQL自己的C API函数连接数据库.我是在Linux平台下开发,所以就采用第二种方法,有很多Api函数,但是常用的就几个,我也是就用到其中的几个. API函数 1.mysql_real_connect() 连接一个mysql服务器 MYSQL *mysq

  • C++与mysql连接遇到的问题汇总

    最近接触了很多数据库的东西,本来是一直接触的是sql server,不过由于项目需要就开始对mysql进行了连接.下面就让我这个菜鸟浅谈下经验吧. 对于C++连接mysql,我不太喜欢多下载一个软件mysqlodbc,所以采用的是通过mysql自己的API函数进行连接: 1.使用API的方式连接,需要加载mysql的头文件和lib文件. 在VS2010的附加包含目录中添加\MySQL\MySQL Server 5.1\include.在安装MySql的目录下找. 把libmysql.dll和li

  • c++连接mysql数据库的两种方法(ADO连接和mysql api连接)

    第一种方法可以实现我当前的需求,通过连接不同的字符串来连接不同的数据库.暂时只连接了mysql,sqlserver,oracle,access.对于access,因为它创建表的SQL语句不太兼容标准SQL语句,需要做一些处理,这里暂时不说.第二种方法只能针对于mysql数据库的连接,不过用这种方法不用安装MyODBC服务器程序. 不管用哪种方法,首先需要安装Mysql数据库,安装方法请看"mysql安装及一些注意点".最好安装一个Navicat for mysql,方便操作mysql数

  • C++用mysql自带的头文件连接数据库

    mysql.h文件在哪,怎么查找.自行百度 #include <mysql/mysql.h> #include <stdio.h> #include<iostream> #include<fstream> #include<string.h> using namespace std; MYSQL *conn; MYSQL_RES *res; MYSQL_ROW row; class people { public: char name[20];

  • 介绍一个针对C++程序的MySQL访问库soci

    一直以来,笔者都在不停寻找一种更人性化的数据库访问方式(并不是说默认的方式不好,而是有时候的确在模块化设计中不太方便). 后来有幸在php中找到codeigniter的ActiveReord,详细参考这篇文章: 抽离CodeIgniter的数据库访问类! 然而c++却始终用着最原始的方式,昨天趁着项目要用的机会,在网上搜索了好久,总算让我找到两套c++的数据库访问框架: soci    litesql 两套代码我都拿下来看了一下,litesql实现了一套完整的代码自动生成,功能强大,但是也很重:

  • 用C++封装MySQL的API的教程

    其实相信每个和mysql打过交道的程序员都应该会尝试去封装一套mysql的接口,这一次的封装已经记不清是我第几次了,但是每一次我希望都能做的比上次更好,更容易使用. 先来说一下这次的封装,遵守了几个原则,其中部分思想是从python借鉴过来的: 1.简单 简单,意味着不为了微小的效率提升,而去把接口搞的复杂.因为本身数据库存储效率的瓶颈并不是那一两次内存copy,代码中随处可以看到以这个为依据的设计.     2.低学习成本 使用一套新库通常意味着投入学习成本,而这次的封装并没有像django那

  • c++连接mysql5.6的出错问题总结

    1.描述:链接的时候出错了,错误提示:无法解析的外部符号 _mysql_init@4,该符号在函数 _main 中被引用 原因:我的机器是64bit WIN7系统,VS2012是32bit的,而MySQL是64bit的,32位工程调用64bit的libmysql.lib,因此连接出错啦. 解决:重新安装32bit的MySQL即可. 2.描述:编译出错, 1>c:\program files (x86)\mysql\mysql server 5.6\include\mysql_com.h(320)

  • C++操作MySQL大量数据插入效率低下的解决方法

    通常来说C++操作MySQL的时候,往Mysql中插入10000条简单数据,速度非常缓慢,居然要5分钟左右, 而打开事务的话,一秒不到就搞定了! 具体实现代码如下: #include <iostream> #include <winsock2.h> #include <string> #include "mysql.h" #pragma comment(lib, "libmysql.lib"); using namespace s

  • C++利用MySQL API连接和操作数据库实例详解

    1.C++连接和操作MySQL的方式 系列文章: MySQL 设计和命令行模式下建立详解 C++利用MySQL API连接和操作数据库实例详解 在Windows平台,我们可以使用ADO.ODBC或者MySQL API进行连接和操作.ADO (ActiveX Data Objects,ActiveX数据对象)是Microsoft提出的一个用于存取数据源的COM组件.它提供了程序语言和统一数据访问方式OLE DB的一个中间层,也就是Microsoft提出的应用程序接口(API)用以实现访问关系或非关

  • C#编程实现连接SQL SERVER数据库实例详解

    本文实例讲述了C#编程实现连接SQL SERVER数据库.分享给大家供大家参考,具体如下: 首先,在SQL SEVER里建立一个名为"Exercise"的数据库名,在该数据库下建立一张名为"lianxi"的表.好,现在开始写代码. 在FORM1里拖一个DATAGIRDVIEW用于显示表,在放一个BUTTON用于执行操作.加入命名空间 复制代码 代码如下: using system.data.sqlclient; private void button1_Click(

  • MySQL命令行导出导入数据库实例详解

    MySQL命令行导出数据库: 1,进入MySQL目录下的bin文件夹:cd MySQL中到bin文件夹的目录 如我输入的命令行:cd C:\Program Files\MySQL\MySQL Server 5.5\bin (或者直接将windows的环境变量path中添加该目录) 2,导出数据库:mysqldump -u 用户名 -p 数据库名 > 导出的文件名 如我输入的命令行:mysqldump -u lmapp -p lmapp -P 3308 > lmapp.sql   (输入后会让你

  • Django+mysql配置与简单操作数据库实例代码

     第一步:下载mysql驱动 cmd进入创建好的django项目目录:使用命令 pip install mysqlclient 等待安装成功! 第二步:在settings.py中配置mysql连接参数(没有mysql的先装mysql) DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '数据库名(你得先在mysql中创建数据库)', 'USER':'mysql用户名(如root)', 'PASSWOR

  • mysql 操作数据库基础详解

    目录 一.介绍 二.SQL分类 三.基本操作 创建 查询 修改 删除 使用数据库 一.介绍 MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性. 是最流行的关系型数据库管理系统之一. 二.SQL分类 SQL语句的五种分类分别是DDL.DML.DDL.DQL.DCL. 数据定义语言(DDL) 用来创建数据库中的各种对象,创建.删除.修改表的结构.关键字:create, drop,alter 等 数据操作语言(DM

  • php mysql PDO 查询操作的实例详解

    php mysql PDO 查询操作的实例详解 <?php $dbh = new PDO('mysql:host=localhost;dbname=access_control', 'root', ''); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $dbh->exec('set names utf8'); /*添加*/ //$sql = "INSERT INTO `user` SET `log

  • R语言对数据库进行操作的实例详解

    数据是关系数据库系统以规范化格式存储. 因此,要进行统计计算,我们将需要非常先进和复杂的Sql查询. 但R语言可以轻松地连接到许多关系数据库,如MySql,Oracle,Sql服务器等,并从它们获取记录作为数据框. 一旦数据在R语言环境中可用,它就变成正常的R语言数据集,并且可以使用所有强大的包和函数来操作或分析. 在本教程中,我们将使用MySql作为连接到R语言的参考数据库. RMySQL包 R语言有一个名为"RMySQL"的内置包,它提供与MySql数据库之间的本地连接. 您可以使

  • Node服务端实战之操作数据库示例详解

    目录 连接数据库 insert语句 简化新增sql update语句 delete语句 连接数据库 本系列是使用node作为服务器开发的操作过程记录,记录一下主要的内容并且整理过程的脉络,以初学者的方式将学习内容记录下来,从0到1逐步的学习node,教程使用过程中用到的是基于express的node框架. const mysql = require('mysql') const db = mysql.createPool({ host: 'localhost', user: 'root', pa

  • MySQL实现数据插入操作的示例详解

    目录 一.方法分类 二.具体方法 三.实例 (1)常规插入 (2)从另一个表导入 (3)插入时数据重复 四.注意事项 (1)不写字段名,需要填充自增ID (2)按字段名填充,可以不录入id 其余注意事项 使用MySQL插入数据时,可以根据需求场景选择合适的插入语句,例如当数据重复时如何插入数据,如何从另一个表导入数据,如何批量插入数据等场景.本文通过给出每个使用场景下的实例来说明数据插入的实现过程和方法. 一.方法分类 二.具体方法 使用场景 作用 语句 注意 常规插入 忽略字段名 insert

  • MySQL数据类型中DECIMAL的用法实例详解

    MySQL数据类型中DECIMAL的用法实例详解 在MySQL数据类型中,例如INT,FLOAT,DOUBLE,CHAR,DECIMAL等,它们都有各自的作用,下面我们就主要来介绍一下MySQL数据类型中的DECIMAL类型的作用和用法. 一般赋予浮点列的值被四舍五入到这个列所指定的十进制数.如果在一个FLOAT(8, 1)的列中存储1. 2 3 4 5 6,则结果为1. 2.如果将相同的值存入FLOAT(8, 4) 的列中,则结果为1. 2 3 4 6. 这表示应该定义具有足够位数的浮点列以便

随机推荐