封装MySQL C API 基本操作
根据我的以前的文章 http://blog.csdn.net/skyhuangdan/article/details/21099929 链接数据库成功后进行封装。
我封装类使用的是VS2005下的win32控制台应用程序编写,预编译头文件了的。
所以要在 stdafx.h 里面加入 :
#include “CMySQL.h”
现在代码奉上:
main函数代码:mysql2.cpp
// mysql2.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" int main() { CMySQL mysql; int re = mysql.Connect("localhost", "root", "123456"); mysql.ReConnect(); char buffer[1024] = {0}; while(1) { memset(buffer, 0, 1024); printf("please input cmd:\n"); if( strcmp( "quit", gets(buffer)) != 0 ) { if( (char) \'1\'== buffer[0] ){ mysql.SelectQuery(buffer+1); }else{ mysql.ModifyQuery(buffer+1); printf("Modify\n"); } }else break; } getchar(); }
CMySQL.h
#pragma once #include <windows.h> #include <my_global.h> #include <mysql.h> #include <iostream> using namespace std; /* #define ERRMSG1(fmt,...) ; sprintf(m_szErrMsg, fmt, __VA_ARGS__); #define ERRMSG2(fmt,args...) ; sprintf(m_szErrMsg, "[%s 第 %d 行 ]; "fmt"\r\n" , __FILE__, __LINE__, ##args); */ class CMySQL { public: CMySQL(void); public: ~CMySQL(void); public: bool m_bConnected; //数据库连接了吗? true--已经连接; false--还没有连接 char m_szErrMsg[1024]; //函数出错后, 错误信息放在此处 int m_iFields; //字段个数 MYSQL m_connection; //连接 MYSQL_RES* m_result; //结果集指针 MYSQL_ROW m_row; //一行, typedef char **MYSQL_ROW; private: string m_sDbIp; //数据库服务器IP string m_sUser; //用户名 string m_sPassword; //口令 public: int Connect(const char* szDbIp, const char* szUser, const char* szPassword); //关闭连接,无论之前是否已经连接,使用这个函数都不会有问题 void CloseConnect(); //判断是否连接 bool IsConnected(); //连接标志 void SetConnected(bool bTrueFalse ); //重新连接 int ReConnect(); //用于执行查询命令,并且把查询到的结果集保存到m_result结果集里面 //!!此函数调用SelectPrint()函数!! int SelectQuery(const char* szSQL); //只是执行SQL命令 int ModifyQuery(const char* szSQL); //返回错误信息 const char* GetErrMsg(); //保存连接参数 void SaveParam(const char* szDbIp, const char* szUser, const char* szPassword); //释放上次的结果 void FreePreResult(); //显示结果? void PrintSelect(); };
CMySQL.cpp:
#include "StdAfx.h" #include "CMySQL.h" CMySQL::CMySQL(void) { SetConnected(false); //把结果集置空 m_result = NULL; //初始化连接 mysql_init(&m_connection); } CMySQL::~CMySQL(void) { //释放上一次的结果集 FreePreResult(); //关闭数据库连接 CloseConnect(); } int CMySQL::Connect(const char* szDbIp, const char* szUser, const char* szPassword) { SaveParam(szDbIp, szUser, szPassword); //先判断释放已连接,防止重复连接 if (IsConnected()) return 0; //连接数据库 if (mysql_real_connect( &m_connection, szDbIp, szUser, szPassword, NULL, 0,NULL, 0) == NULL) { sprintf(m_szErrMsg,"%s" ,mysql_error(&m_connection)); return -1; } printf("[mysql] conn to %s [user:%s] succ!\r\n", szDbIp, szUser); //设置连接标志为 true SetConnected(true); return 0; } void CMySQL::CloseConnect() { //不论m_connection曾经是否连接过, 这样关闭都不会有问题 mysql_close(&m_connection); SetConnected(false); } bool CMySQL::IsConnected() { return m_bConnected; } void CMySQL::SetConnected(bool bTrueFalse) { m_bConnected = bTrueFalse; } void CMySQL::FreePreResult() { if (m_result != NULL) { mysql_free_result(m_result); m_result = NULL; } } int CMySQL::SelectQuery(const char* szSQL) { //如果查询串是空指针,则返回 if (szSQL == NULL) { sprintf(m_szErrMsg,"%s", "szSQL==NULL"); return -1; } //如果还没有连接,则返回 if (!IsConnected()) { sprintf(m_szErrMsg,"%s" , "还没有建立连接"); return -2; } try //这些语句与连接有关,出异常时就重连 { //查询 if (mysql_real_query(&m_connection, szSQL, strlen(szSQL)) != 0) { sprintf(m_szErrMsg,"%s" , mysql_error(&m_connection)); printf("%s", mysql_error(&m_connection)); printf("ReConnect() is called, select111 !!!***@\r\n"); int nRet = ReConnect(); if (nRet != 0) return -3; // if (mysql_real_query(&m_connection, szSQL, strlen(szSQL)) != 0) return -33; // } //释放上一次的结果集 FreePreResult(); //取结果集 m_result = mysql_store_result(&m_connection); if (m_result == NULL) { sprintf(m_szErrMsg,"%s" , mysql_error(&m_connection)); return -4; } } catch (...) { printf("ReConnect() is called, select !!!***@!@\r\n"); ReConnect(); return -5; } //取字段的个数 m_iFields = mysql_num_fields(m_result); //查询完过后进行打印出来 this->PrintSelect(); return 0; } int CMySQL::ReConnect() { CloseConnect(); //连接数据库 SetConnected(false); //把结果集置空 m_result = NULL; //初始化连接 mysql_init(&m_connection); if (mysql_real_connect(&m_connection, m_sDbIp.c_str(), m_sUser.c_str(),m_sPassword.c_str(), NULL, 0, NULL, 0) == NULL) { sprintf(m_szErrMsg,"%s" , mysql_error(&m_connection)); return -1; } //设置连接标志为 true SetConnected(true); return 0; } const char* CMySQL::GetErrMsg() { return m_szErrMsg; } void CMySQL::SaveParam(const char* szDbIp, const char* szUser, const char* szPassword) { m_sDbIp = szDbIp; //数据库服务器IP m_sUser = szUser; //用户名 m_sPassword = szPassword; //口令 } void CMySQL::PrintSelect() { printf("\n------------------------------------------------\n"); int num_fields = mysql_num_fields(m_result); while ( m_row = mysql_fetch_row( m_result) ) { for( int i = 0; i < num_fields; i++ ) { if(m_row[i]) printf("%s ", m_row[i]); else printf("NULL"); } printf("\n"); } printf("\n------------------------------------------------\n"); } int CMySQL::ModifyQuery(const char* szSQL) { //如果查询串是空指针,则返回 if (szSQL == NULL) { sprintf(m_szErrMsg,"%s", "szSQL==NULL"); return -1; } //如果还没有连接,则返回 if (!IsConnected()) { sprintf(m_szErrMsg,"%s", "还没有建立连接"); return -2; } try //这些语句与连接有关,出异常时就重连 { //查询, 实际上开始真正地修改数据库 if (mysql_real_query(&m_connection, szSQL, strlen(szSQL)) != 0) { sprintf(m_szErrMsg,"%s", mysql_error(&m_connection)); return -3; } } catch (...) { printf("ReConnect() is called ,modify!!!***\r\n"); ReConnect(); return -5; } return 0; }
注:
对于输入的MySQL命令错误的情况下,程序会连接一遍,在程序关闭过后用于连接的关键字【MYSQL m_connection; 】必须要初始化,否则程序会出错。
还有,重连过后,必须重新USE XXXXX; 因为重新连接那里并没有自动连接你之前USE过的数据库。