首页 > 代码库 > 实例讲解如何使用C++操作MySQL数据库类

实例讲解如何使用C++操作MySQL数据库类

用C++操作MySQL数据库类:

注释:这几个类对处理不是很大数据量的操作是很理想的, 但不适宜特大型的数据的查询,因为源码中将查询到的数据直接放入了内存。

/*
*  project:
*           通用模块 ( 用 c++ 处理  mysql 数据库类,像ADO )
*                 
*  description:
*
*           通过DataBase,RecordSet,Record,Field类,实现对mysql数据库的操作
*    包括连接、修改、添加、删除、查询等等,像ADO一样操作数据库,使
*    用方便
*
*          ( the end of this file have one sample,
*                    welcom to use... )
*
*
*  file:zlb_mysql.h
*
*  author: @ zlb

*  time:2005-12-12 
*
*

--*/

#ifndef ZLB_MYSQL_H
#define ZLB_MYSQL_H

#include "mysql.h"

#include <iostream>
#include <vector>
#include <string>

using namespace std;

namespace zlb_mysql{
/*
  * 字段操作
*/
class Field
{
public :
  /* 字段名称 */
  vector<string> m_name;
  /* 字段类型 */
  vector<enum_field_types> m_type;
public :
  Field();
  ~Field();
  /* 是否是数字 */
  bool IsNum(int num);
  /* 是否是数字 */
  bool IsNum(string num);
  /* 是否是日期 */
  bool IsDate(int num);
  /* 是否是日期 */
  bool IsDate(string num);
  /* 是否是字符 */
  bool IsChar(int num);
  /* 是否是字符 */
  bool IsChar(string num);
  /* 是否为二进制数据 */
  bool IsBlob(int num);
  /* 是否为二进制数据 */
  bool IsBlob(string num);
  /* 得到指定字段的序号 */
  int GetField_NO(string field_name);
};
/*
  * 1 单条记录
  * 2 [int ]操作 [""]操作
*/
class Record
{
public:
  /* 结果集 */
  vector<string> m_rs;
  /* 字段信息 占用4字节的内存 当记录数很大是回产生性能问题 */
  Field *m_field;
public :
  Record(){};
  Record(Field* m_f);
  ~Record();
  void SetData(string value);
  /* [""]操作 */
  string operator[](string s);
  string operator[](int num);
  /* null值判断 */
  bool IsNull(int num);
  bool IsNull(string s);
  /* 用 value tab value 的形式 返回结果 */
  string GetTabText();
};
/*
  * 1 记录集合
  * 2 [int ]操作 [""]操作
  * 3 表结构操作
  * 4 数据的插入修改
*/
class RecordSet
{
private :
  /* 记录集 */
  vector<Record> m_s;
  /* 游标位置*/
  unsigned long pos;
  /* 记录数 */
  int m_recordcount;
  /* 字段数 */
  int m_field_num;
  /* 字段信息 */
  Field  m_field;
  MYSQL_RES * res ;
  MYSQL_FIELD * fd ;
  MYSQL_ROW row;
  MYSQL* m_Data ;
public :
  RecordSet();
  RecordSet(MYSQL *hSQL);
  ~RecordSet();
  /* 处理返回多行的查询,返回影响的行数 */
  int ExecuteSQL(const char *SQL);
  /* 得到记录数目 */
  int GetRecordCount();
  /* 得到字段数目 */
  int GetFieldNum();
  /* 向下移动游标 */
  long MoveNext();
  /* 移动游标 */
  long Move(long length);
  /* 移动游标到开始位置 */
  bool MoveFirst();
  /* 移动游标到结束位置 */
  bool MoveLast();
  /* 获取当前游标位置 */
  unsigned long GetCurrentPos()const;
  /* 获取当前游标的对应字段数据 */
  bool GetCurrentFieldValue(const char * sFieldName,char *sValue);
  bool GetCurrentFieldValue(const int iFieldNum,char *sValue);
  /* 获取游标的对应字段数据 */
  bool GetFieldValue(long index,const char * sFieldName,char *sValue);
  bool GetFieldValue(long index,int iFieldNum,char *sValue);
  /* 是否到达游标尾部 */
  bool IsEof();

  /* 返回字段 */
  Field* GetField();
  /* 返回字段名 */
  const char * GetFieldName(int iNum);
  /* 返回字段类型 */
  const int GetFieldType(char * sName);
  const int GetFieldType(int iNum);
  /* 返回指定序号的记录 */
  Record operator[](int num);

};
/*
  * 1 负责数据库的连接关闭
  * 2 执行sql 语句(不返回结果)
  * 3 处理事务
*/
class DataBase
{
public :
  DataBase();
  ~DataBase();
private :
  /* msyql 连接句柄 */
  MYSQL* m_Data;
public :
  /* 返回句柄 */
  MYSQL * GetMysql();
  /* 连接数据库 */
  int Connect(string host, string user,
   string passwd, string db,
   unsigned int port,
   unsigned long client_flag);
  /* 关闭数据库连接 */
  void DisConnect();
  /* 执行非返回结果查询 */
  int ExecQuery(string sql);
  /* 测试mysql服务器是否存活 */
  int Ping();
  /* 关闭mysql 服务器 */
  int ShutDown();
  /* 主要功能:重新启动mysql 服务器 */
  int ReBoot();
  /*
  * 说明:事务支持InnoDB or BDB表类型
        */
  /* 主要功能:开始事务 */
  int Start_Transaction();
  /* 主要功能:提交事务 */
  int Commit();
  /* 主要功能:回滚事务 */
  int Rollback();
  /* 得到客户信息 */
  const char * Get_client_info();
  /* 主要功能:得到客户版本信息 */
  const unsigned long  Get_client_version();
  /* 主要功能:得到主机信息 */
  const char * Get_host_info();
  /* 主要功能:得到服务器信息 */
  const char * Get_server_info();
  /*主要功能:得到服务器版本信息*/
  const unsigned long  Get_server_version();
  /*主要功能:得到 当前连接的默认字符集*/
  const char *  Get_character_set_name();
  /* 主要功能返回单值查询  */
  char * ExecQueryGetSingValue(string sql);
  /* 得到系统时间 */
  const char * GetSysTime();
  /* 建立新数据库 */
  int Create_db(string name);
  /* 删除制定的数据库*/
  int Drop_db(string name);
};
};

#endif //ZLB_MYSQL_H

/*
*  project:
*           通用模块 ( 用 c++ 处理  mysql 数据库类,像ADO )
*                 
*  description:
*
*           通过DataBase,RecordSet,Record,Field类,实现对mysql数据库的操作
*    包括连接、修改、添加、删除、查询等等,像ADO一样操作数据库,使
*    用方便
*
*          ( the end of this file have one sample,
*                    welcom to use... )
*
*
*  file:zlb_mysql.cpp
*
*  author: @ zlb

*  time:2005-12-12 
*
*

--*/

#include "stdafx.h"
#include "zlb_mysql.h"

namespace zlb_mysql{

/* +++++++++++++++++++++++++++++++++++++++++++++++++++ */
/*
  * 字段操作
*/
Field::Field(){}
Field::~Field(){}
/*
  * 是否是数字
*/
bool Field::IsNum(int num)
{
  if(IS_NUM(m_type[num]))
   return true;
  else
   return false;
}
/*
  * 是否是数字
*/
bool Field::IsNum(string num)
{
  if(IS_NUM(m_type[GetField_NO(num)]))
   return true;
  else
   return false;
}
/*
  * 是否是日期
*/
bool Field::IsDate(int num)
{
  if( FIELD_TYPE_DATE == m_type[num] ||
   FIELD_TYPE_DATETIME == m_type[num] )
   return true;
  else
   return false;
}
/* 是否是日期 */
bool Field::IsDate(string num)
{
  int temp;
  temp=GetField_NO(num);
  if(FIELD_TYPE_DATE == m_type[temp] ||
     FIELD_TYPE_DATETIME == m_type[temp] )
   return true;
  else
   return false;
}
/*
  * 是否是字符
*/
bool Field::IsChar(int num)
{
  if(m_type[num]==FIELD_TYPE_STRING  ||
   m_type[num]==FIELD_TYPE_VAR_STRING ||
   m_type[num]==FIELD_TYPE_CHAR )
   return true;
  else
   return false;
}
/*
  * 是否是字符
*/
bool Field::IsChar(string num)
{
  int temp;
  temp=this->GetField_NO (num);
  if(m_type[temp]==FIELD_TYPE_STRING  ||
   m_type[temp]==FIELD_TYPE_VAR_STRING ||
   m_type[temp]==FIELD_TYPE_CHAR )
   return true;
  else
   return false;
}
/*
  * 是否为二进制数据
*/
bool Field::IsBlob(int num)
{
  if(IS_BLOB(m_type[num]))
   return true;
  else
   return false;
}
/*
  * 是否为二进制数据
*/
bool Field::IsBlob(string num)
{
  if(IS_BLOB(m_type[GetField_NO(num)]))
   return true;
  else
   return false;
}
/*
  * 得到指定字段的序号
*/
int Field::GetField_NO(string field_name)
{  
  for(unsigned int i=0;i<m_name.size ();i++)
  {
   if(!m_name[i].compare (field_name))
    return i;
  }
  return -1;
}
/*-----------------------------------------------------*/

/* +++++++++++++++++++++++++++++++++++++++++++++++++++ */
/*
  * 1 单条记录
  * 2 [int ]操作 [""]操作
*/

Record::Record(Field * m_f)
{
  m_field =m_f;
}
Record::~Record(){};

void Record::SetData(string value)
{
  m_rs.push_back (value);
}
/* [""]操作 */
string Record::operator[](string s)
{
  return m_rs[m_field->GetField_NO(s)];
}
string Record::operator[](int num)
{
  return m_rs[num];
}
/* null值判断 */
bool Record::IsNull(int num)
{
  if("" == m_rs[num].c_str ())
   return true;
  else
   return false;
}
bool Record::IsNull(string s)
{
  if("" == m_rs[m_field->GetField_NO(s)].c_str())
   return true;
  else return false;
}
/* 主要-功能:用 value tab value 的形式 返回结果 */
string Record::GetTabText()
{
  string temp;
  for(unsigned int i=0 ;i<m_rs.size();i++)
  {
   temp+=m_rs[i];
   if(i<m_rs.size ()-1)
    temp+="\t";
  }
  return temp;
}
/*-----------------------------------------------------*/

/* +++++++++++++++++++++++++++++++++++++++++++++++++++ */
/*
  * 1 记录集合
  * 2 [int ]操作 [""]操作
  * 3 表结构操作
  * 4 数据的插入修改
*/
RecordSet::RecordSet()
{
  res = NULL;
  row = NULL;
  pos = 0;
}
RecordSet::RecordSet(MYSQL *hSQL)
{
  res = NULL;
  row = NULL;
  m_Data = http://www.mamicode.com/hSQL;
  pos = 0;
}
RecordSet::~RecordSet()
{
}
/*
  * 处理返回多行的查询,返回影响的行数
  * 成功返回行数,失败返回-1
*/
int RecordSet::ExecuteSQL(const char *SQL)
{
  if ( !mysql_real_query(m_Data,SQL,strlen(SQL)))
  {
   //保存查询结果
   res = mysql_store_result(m_Data );
   //得到记录数量
   m_recordcount = (int)mysql_num_rows(res) ;
   //得到字段数量
   m_field_num = mysql_num_fields(res) ;
   for (int x = 0 ; fd = mysql_fetch_field(res); x++)
   {
    m_field.m_name.push_back(fd->name);
    m_field.m_type.push_back(fd->type);
   }
   //保存所有数据
   while (row = mysql_fetch_row(res))
   {
    Record temp(&m_field);
    for (int k = 0 ; k < m_field_num ; k++ )
    {
     if(row[k]==NULL||(!strlen(row[k])))
     {
      temp.SetData ("");
     }
     else
     {
      temp.SetData(row[k]);
     }
    }
    //添加新记录
    m_s.push_back (temp);
   }
   mysql_free_result(res ) ;

   return m_s.size();
  }
  return -1;
}
/*
  * 向下移动游标
  * 返回移动后的游标位置
*/
long RecordSet::MoveNext()
{
  return (++pos);
}
/* 移动游标 */
long  RecordSet::Move(long length)
{
  int l = pos + length;
  if(l<0)
  {
   pos = 0;
   return 0;
  }else
  {
   if(l >= m_s.size())
   {
    pos = m_s.size()-1;
    return pos;
   }else
   {
    pos = l;
    return pos;
   }
  }
}
/* 移动游标到开始位置 */
bool RecordSet::MoveFirst()
{
  pos = 0;
  return true;
}
/* 移动游标到结束位置 */
bool RecordSet::MoveLast()
{
  pos = m_s.size()-1;
  return true;
}
/* 获取当前游标位置 */
unsigned long RecordSet::GetCurrentPos()const
{
  return pos;
}
/* 获取当前游标的对应字段数据 */
bool RecordSet::GetCurrentFieldValue(const char * sFieldName,
           char *sValue)
{
  strcpy(sValue,m_s[pos][sFieldName].c_str());
  return true;
}
bool RecordSet::GetCurrentFieldValue(const int iFieldNum,char *sValue)
{
  strcpy(sValue,m_s[pos][iFieldNum].c_str());
  return true;
}
/* 获取游标的对应字段数据 */
bool RecordSet::GetFieldValue(long index,const char * sFieldName,
        char *sValue)
{
  strcpy(sValue,m_s[index][sFieldName].c_str());
  return true;
}
bool RecordSet::GetFieldValue(long index,int iFieldNum,char *sValue)
{
  strcpy(sValue,m_s[index][iFieldNum].c_str());
  return true;
}
/* 是否到达游标尾部 */
bool RecordSet::IsEof()
{
  return (pos == m_s.size())?true:false;
}
/*
  * 得到记录数目
*/
int RecordSet::GetRecordCount()
{
  return m_recordcount;
}
/*
  * 得到字段数目
*/
int RecordSet::GetFieldNum()
{
  return m_field_num;
}
/*
  * 返回字段
*/
Field * RecordSet::GetField()
{
  return &m_field;
}
/* 返回字段名 */
const char * RecordSet::GetFieldName(int iNum)
{
  return m_field.m_name.at(iNum).c_str();
}
/* 返回字段类型 */
const int RecordSet::GetFieldType(char * sName)
{
  int i = m_field.GetField_NO(sName);
  return m_field.m_type.at(i);
}
const int RecordSet::GetFieldType(int iNum)
{
  return m_field.m_type.at(iNum);
}
/*
  * 返回指定序号的记录
*/
Record RecordSet::operator[](int num)
{
  return m_s[num];
}

/* -------------------------------------------------- */

/* +++++++++++++++++++++++++++++++++++++++++++++++++++ */
/*
* 1 负责数据库的连接关闭
* 2 执行sql 语句(不返回结果)
* 3 处理事务
*/
DataBase::DataBase()
{
  m_Data = http://www.mamicode.com/NULL;
}
DataBase::~DataBase()
{
  if(NULL != m_Data)
  {
   DisConnect();
  }
}
/* 返回句柄 */
MYSQL * DataBase::GetMysql()
{
  return m_Data;
}
/*
  * 主要功能:连接数据库
  * 参数说明:
  * 1 host 主机ip地址或者时主机名称
  * 2 user 用户名
  * 3 passwd 密码
  * 4 db 欲连接的数据库名称
  * 5 port 端口号
  * 6 uinx 嵌套字
  * 7 client_flag 客户连接参数
  * 返回值: 0成功 -1 失败
*/
int DataBase::Connect(string host, string user,
        string passwd, string db,
        unsigned int port,
        unsigned long client_flag)
{
  if((m_Data = http://www.mamicode.com/mysql_init(NULL)) && 
   mysql_real_connect( m_Data, host.c_str(),
        user.c_str(), passwd.c_str(),
        db.c_str(),port , NULL,
        client_flag))
  {
   //选择制定的数据库失败
   if ( mysql_select_db( m_Data, db.c_str () ) < 0 )
   {
    mysql_close( m_Data) ;
    return -1 ;
   }
  }
  else
  {
   //初始化mysql结构失败
   mysql_close( m_Data );
   return -1 ;
  }
  //成功
  return 0;
}
/*
  * 关闭数据库连接
*/
void DataBase::DisConnect( )
{
  mysql_close(m_Data) ;
}
/*
  * 主要功能: 执行非返回结果查询
  * 参数:sql 待执行的查询语句
  * 返回值; n为成功 表示受到影响的行数 -1 为执行失败
*/
int DataBase::ExecQuery(string sql)
{
  if(!mysql_real_query(m_Data,sql.c_str (),(unsigned long)sql.length()) )
  {
   //得到受影响的行数
   return (int)mysql_affected_rows(m_Data) ;
  }
  else
  {
   //执行查询失败
   return -1;
  }
}
/*
  * 主要功能:测试mysql服务器是否存活
  * 返回值:0 表示成功 -1 失败
*/
int DataBase::Ping()
{
  if(!mysql_ping(m_Data))
   return 0;
  else
   return -1;
}
/*
  *  主要功能:关闭mysql 服务器
  * 返回值;0成功 -1 失败
*/
int DataBase::ShutDown()
{
  if(!mysql_shutdown(m_Data,SHUTDOWN_DEFAULT))
   return 0;
  else
   return -1;
}
/*
  * 主要功能:重新启动mysql 服务器
  * 返回值;0表示成功 -1 表示失败
*/
    int DataBase::ReBoot()
{
  if(!mysql_reload(m_Data))
   return 0;
  else
   return -1;
}

/*
  * 说明:事务支持InnoDB or BDB表类型
    */
    /*
  * 主要功能:开始事务
*/
int DataBase::Start_Transaction()
{
  if(!mysql_real_query(m_Data, "START TRANSACTION" ,
   (unsigned long)strlen("START TRANSACTION") ))
  {
   return 0;
  }
  else
   //执行查询失败
   return -1;
}
/*
  * 主要功能:提交事务
  * 返回值:0 表示成功 -1 表示失败
*/
int DataBase::Commit()
{
  if(!mysql_real_query( m_Data, "COMMIT",
   (unsigned long)strlen("COMMIT") ) )
  {
   return 0;
  }
  else     
   //执行查询失败
   return -1;
}
/*
  * 主要功能:回滚事务
  * 返回值:0 表示成功 -1 表示失败
*/
int DataBase::Rollback()
{
  if(!mysql_real_query(m_Data, "ROLLBACK",
   (unsigned long)strlen("ROLLBACK") ) )
   return 0;
  else 
   //执行查询失败
   return -1;
}
/* 得到客户信息 */
const char * DataBase::Get_client_info()
{
  return mysql_get_client_info();
}
/*主要功能:得到客户版本信息*/
const unsigned long DataBase::Get_client_version()
{
  return mysql_get_client_version();
}
/* 主要功能:得到主机信息 */
const char * DataBase::Get_host_info()
{
  return mysql_get_host_info(m_Data);
}
/* 主要功能:得到服务器信息 */
const char * DataBase::Get_server_info()
{
  return mysql_get_server_info( m_Data );
}
/* 主要功能:得到服务器版本信息 */
const unsigned long   DataBase::Get_server_version()
{
  return mysql_get_server_version(m_Data);
}
/*主要功能:得到 当前连接的默认字符集*/
const char *  DataBase::Get_character_set_name()
{
  return mysql_character_set_name(m_Data);
}
/*
  * 主要功能返回单值查询
*/
char * DataBase::ExecQueryGetSingValue(string sql)
{
  MYSQL_RES * res;
  MYSQL_ROW row ;
  char *p = NULL;
  if(!mysql_real_query( m_Data, sql.c_str(),(unsigned long)sql.length()))
  {
   //保存查询结果
   res = mysql_store_result( m_Data ) ;
   row = mysql_fetch_row( res ) ;
   p = ((row[0]==NULL)||(!strlen(row[0])))?"-1":row[0];
   mysql_free_result( res ) ;
  }
  else
   //执行查询失败
   p = "-1";
  return p;
}
/*
  * 得到系统时间
*/
const char * DataBase::GetSysTime()
{
  return ExecQueryGetSingValue("select now()");
}
/*
  *  主要功能:建立新数据库
  * 参数:name 为新数据库的名称
  * 返回:0成功 -1 失败
*/
int DataBase::Create_db(string name)
{
  string temp ;
  temp="CREATE DATABASE ";
  temp+=name;
  if(!mysql_real_query( m_Data,temp.c_str () ,
   (unsigned long)temp.length ()) )
   return 0;
  else
   //执行查询失败
   return -1;
}
/*
  * 主要功能:删除制定的数据库
  * 参数:name 为欲删除数据库的名称
  * 返回:0成功 -1 失败
*/
int DataBase::Drop_db(string name)
{
  string temp ;
  temp="DROP DATABASE ";
  temp+=name;
  if(!mysql_real_query( m_Data,temp.c_str () ,
   (unsigned long)temp.length ()) )
   return 0;
  else
   //执行查询失败
   return -1;
}
/*-----------------------------------------------------*/
};

/*
*  使用例子
*/
#include "zlb_mysql.h"
using namespace std;
void main()
{
zlb_mysql::DataBase zlb;
//连接数据库
if(-1 == zlb.Connect("localhost"/*本地数据库,可以是远程 ip*/,
            "root"/*用户名*/,"apple"/*密码*/,
            "test"/*数据库名*/,
            0,0/*两个标志,mysql文档有说明,一般为0*/))
{
  std::cout<<"connect failed "<<std::endl;
}
else
{
  std::cout<<"connect success"<<std::endl;
}
//通过返回的数据库句柄,建立记录急,你可以通过返回的这个句柄建立多个记录急
zlb_mysql::RecordSet rs(zlb.GetMysql());
rs.ExecuteSQL("select * from testtable");//这个语句大家都知道是什么意思了

cout<<rs.GetRecordCount()/*返回的总的记录数*/<<endl;
cout<<rs.GetFieldNum()/*返回的总的字段数*/<<endl;
cout<<rs[0].GetTabText()/*返回第一条记录,你也可以rs[1].GetTabText()
                           如果你有多条记录,
             */
   <<endl;
/*实现遍列,也可以使用后面的遍列方式*/
for(int i=0;i<rs.GetRecordCount();++i)
{
   for(int j =0;j<rs.GetFieldNum();++j)
    cout<<rs[i][j];
   cout<<endl;
}
zlb_mysql::Field *fd = rs.GetField();/*你可以通过这样的方式,获取字段的信息*/
cout<<fd->GetField_NO("Password")/*返回我表里的 Password 字段的位置,不
                   是记录的位置*/
   <<endl;
cout<<rs[0]["Password"]<<endl;/*输出第0行第Password列的值*/
cout<<rs[0][fd->GetField_NO("Password")]<<endl;/*你也可以这样*/
cout<<rs.GetFieldName(0)/*获取字段的名字*/<<endl;
cout<<rs.GetFieldType("UserName")/*获取字段的类型,是mysql里定义的*/<<endl;

cout<<rs.GetCurrentPos()/*获取当前记录的位置*/<<endl;
char s[50];
rs.GetCurrentFieldValue(1,s);/*获取当前记录对应字段的值*/
cout<<s<<endl;

cout<<rs.Move(1)<<endl;/*移动游标,正数往前 负数往后*/
cout<<rs.GetCurrentPos()<<endl;
rs.GetCurrentFieldValue(1,s);
cout<<s<<endl;

rs.MoveFirst();/*移动游标到最前*/
while(!rs.IsEof()/*判断是否到达游标尾,实现遍列*/)
{
  rs.GetCurrentFieldValue("UserName",s);
  cout<<s<<"\t";
  rs.GetCurrentFieldValue("Password",s);
  cout<<s<<"\t\n";
  rs.MoveNext();
}

rs.GetFieldValue(0,"UserName",s);/*获取指定行 的记录值*/
cout<<s<<"\t";
rs.GetFieldValue(0,"Password",s);
cout<<s<<"\t\n";
}