下载地址:
https://dev.mysql.com/downloads/connector/cpp/
一、 创建项目并配置所需头文件及库
(一) 创建空项目
使用VS2015创建空项目
(二) 添加项目所需头文件所在文件夹
右键项目选择属性,进入C/C++ => 常规 => 附加包含目录,添加D:\mysql-5.7.19-win64\include(根据自己安装的MySQL版本及地址填写)
(三) 添加所需库
仍在属性页,进入链接器 => 常规 => 附加库目录,添加D:\mysql-5.7.19-winx64\lib(根据自己情况填写)
(四) 添加libmysql.dll
在项目的.\x64\Debug\中添加libmysql.dll(从计算机的资源管理器中添加),该dll文件在D:\mysql-5.7.19-winx64\lib目录下
若为执行这步会出现以下错误:
二、 代码测试
(一) 添加项,将下列代码复制运行即可
#include "stdio.h" #include "mysql.h" int main() { MYSQL * con; //= mysql_init((MYSQL*) 0); MYSQL_RES *res; MYSQL_ROW row; char tmp[400]; //database configuartion char dbuser[30] = "root"; char dbpasswd[30] = "123456"; // it must be changed char dbip[30] = "localhost"; char dbname[50] = "hospital"; char tablename[50] = "bl"; char *query = NULL; int x; int y; int rt;//return value unsigned int t; int count = 0; con = mysql_init((MYSQL*)0); if (con != NULL && mysql_real_connect(con, dbip, dbuser, dbpasswd, dbname, 3306, NULL, 0)) { if (!mysql_select_db(con, dbname)) { printf("Select successfully the database!\n"); con->reconnect = 1; query = "set names \'GBK\'"; rt = mysql_real_query(con, query, strlen(query)); if (rt) { printf("Error making query: %s !!!\n", mysql_error(con)); } else { printf("query %s succeed!\n", query); } } } else { MessageBoxA(NULL, "Unable to connect the database,check your configuration!", "", NULL); } //sprintf(tmp, "insert into %s values(%s,%d,%d)", tablename, "null", x, y); //注意如何向具有自增字段的数据库中插入记录 sprintf(tmp, "insert into bl values(null,'x','x','x','x')"); rt = mysql_real_query(con, tmp, strlen(tmp)); if (rt) { printf("Error making query: %s !!!\n", mysql_error(con)); } else { printf("%s executed!!!\n", tmp); } sprintf(tmp, "select * from %s", tablename); rt = mysql_real_query(con, tmp, strlen(tmp)); if (rt) { printf("Error making query: %s !!!\n", mysql_error(con)); } else { printf("%s executed!!!\n", tmp); } res = mysql_store_result(con);//将结果保存在res结构体中 while (row = mysql_fetch_row(res)) { for (t = 0; t<mysql_num_fields(res); t++) { printf("%s ", row[t]); } printf(".............\n"); count++; } printf("number of rows %d\n", count); printf("mysql_free_result...\n"); mysql_free_result(res); mysql_close(con); system("pause"); return 0; }
看过很多C或是C++操作MySQL数据库的文章,大部分太吃力了,甚至有一部分根本没有很好的组织文字,初学者比较难以接受,即使是C++或是C高手也是比较难看懂。写这篇文章的目的不是别的,就一个,告诉您用MySQL的C API直接操作MySQL数据,并做了比较高效的封装,可以帮助开发人员大幅度提高采用MySQL的C API操作MySQL数据库的效率。
直接进入主题:
1、 准备工作
MySQL数据库安装之后在/MySQL Server 5.0/lib/opt目录下有所需要的各种文件,我们需要的只是以下几个:
libmysql.lib
libmysql.dll
同时需要/MySQL Server 5.0/include目录下的几个文件:
mysql_version.h
my_list.h
mysql_com.h
mysql_time.h
mysql.h
my_alloc.h
typelib.h
准备Socket的基本文件
在VC的安装目录Microsoft Visual Studio/VC98/Lib下找到:
WS2_32.LIB
把这些文件先准备好
2、 使用VC的AppWizard建立一个Win32 Console Application,其实可以是Dialog工程或是其他类型工程,比如工程取名CMySQL
3、 把刚才准备好的文件拷贝你的工程目录下,和普通的CPP文件在同一个目录即可
4、 建立之后,在VC的菜单栏点击Project(项目)->Settings(设置),弹出对话框,选择Link标签进入Link设置,在Object/library modules 的框里面加入
libmysql.lib[有个空格]WS2_32.LIB
5、 在工程建立添加以下两个文件:
第一个文件头文件:VspdCTOMySQL.h
/****************************MYSQL IN C*******************************/ /*************************tianqiweiqi.com ****************************/ /*************************李克喜**************************************/ #include <stdio.h> #include <string> #include <afxsock.h> #include "mysql.h" using namespace std; class VspdCToMySQL { public: //变量 MYSQL mysql; /* 构造函数和稀构函数 */ VspdCToMySQL(); ~VspdCToMySQL(); /* 主要的功能: 初始化数据库 连接数据库 设置字符集 入口参数: host :MYSQL服务器IP port:数据库端口 Db:数据库名称 user:数据库用户 passwd:数据库用户的密码 charset:希望使用的字符集 Msg:返回的消息,包括错误消息 出口参数: int :0表示成功;1表示失败 */ int ConnMySQL(char *host,char * port,char * Db,char * user,char* passwd,char * charset,char * Msg); /* 主要的功能: 查询数据 入口参数: SQL:查询的SQL语句 Cnum:查询的列数 Msg:返回的消息,包括错误消息 出口参数: string 准备放置返回的数据,多条记录则用0x06隔开,多个栏位用0x05隔开 如果 返回的长度= 0,责表示舞结果 */ string SelectData(char * SQL,int Cnum ,char * Msg); /* 主要功能: 插入数据 入口参数 SQL:查询的SQL语句 Msg:返回的消息,包括错误消息 出口参数: int :0表示成功;1表示失败 */ int InsertData(char * SQL,char * Msg); /* 主要功能: 修改数据 入口参数 SQL:查询的SQL语句 Msg:返回的消息,包括错误消息 出口参数: int :0表示成功;1表示失败 */ int UpdateData(char * SQL,char * Msg); /* 主要功能: 删除数据 入口参数 SQL:查询的SQL语句 Msg:返回的消息,包括错误消息 出口参数: int :0表示成功;1表示失败 */ int DeleteData(char * SQL,char * Msg); /* 主要功能: 关闭数据库连接 */ void CloseMySQLConn(); };
第二个文件实现文件:VspdCTOMySQL.cpp
/****************************MYSQL IN C*******************************/ /*************************tianqiweiqi.com ****************************/ /*************************李克喜**************************************/ #include "stdafx.h" #include "VspdCTOMySQL.h" VspdCToMySQL::VspdCToMySQL() { } VspdCToMySQL::~VspdCToMySQL() { } //初始化数据 int VspdCToMySQL::ConnMySQL(char *host,char * port ,char * Db,char * user,char* passwd,char * charset,char * Msg) { if( mysql_init(&mysql) == NULL ) { Msg = "inital mysql handle error"; return 1; } if (mysql_real_connect(&mysql,host,user,passwd,Db,0,NULL,0) == NULL) { Msg = "Failed to connect to database: Error"; return 1; } if(mysql_set_character_set(&mysql,"GBK") != 0) { Msg = "mysql_set_character_set Error"; return 1; } return 0; } //查询数据 string VspdCToMySQL::SelectData(char * SQL,int Cnum,char * Msg) { MYSQL_ROW m_row; MYSQL_RES *m_res; char sql[2048]; sprintf(sql,SQL); int rnum = 0; char rg = 0x06;//行隔开 char cg = {0x05};//字段隔开 if(mysql_query(&mysql,sql) != 0) { Msg = "select ps_info Error"; return ""; } m_res = mysql_store_result(&mysql); if(m_res==NULL) { Msg = "select username Error"; return ""; } string str(""); while(m_row = mysql_fetch_row(m_res)) { for(int i = 0;i < Cnum;i++) { str += m_row[i]; str += rg; } str += rg; rnum++; } mysql_free_result(m_res); return str; } //插入数据 int VspdCToMySQL::InsertData(char * SQL,char * Msg) { char sql[2048]; sprintf(sql,SQL); if(mysql_query(&mysql,sql) != 0) { Msg = "Insert Data Error"; return 1; } return 0; } //更新数据 int VspdCToMySQL::UpdateData(char * SQL,char * Msg) { char sql[2048]; sprintf(sql,SQL); if(mysql_query(&mysql,sql) != 0) { Msg = "Update Data Error"; return 1; } return 0; } //删除数据 int VspdCToMySQL::DeleteData(char * SQL,char * Msg) { char sql[2048]; sprintf(sql,SQL); if(mysql_query(&mysql,sql) != 0) { Msg = "Delete Data error"; return 1; } return 0; } //关闭数据库连接 void VspdCToMySQL::CloseMySQLConn() { mysql_close(&mysql); } 6、 在main函数,(如果是其他工程级不是main了,可能是一个按钮里面的代码块)添加 一些代码,添加之后如下: #include "stdafx.h" #include "VspdCTOMySQL.h" int main(int argc, char* argv[]) { char* host="MYSQL服务器IP"; char* user="root"; char* port ="3306"; char* passwd="用户密码"; char* dbname="数据库名称"; char* charset = "GBK";//支持中文 char* Msg = "";//消息变量 //初始化 VspdCToMySQL * vspdctomysql = new VspdCToMySQL; if(vspdctomysql->ConnMySQL(host,port,dbname,user,passwd,charset,Msg) == 0) printf("连接成功/r/n"); else printf(Msg); //查询 char * SQL = "SELECT ids,username,passwd,address FROM vcaccesstest"; string str = vspdctomysql->SelectData(SQL,4,Msg); if( str.length() > 0 ) { printf("查询成功/r/n"); printf(str.data()); printf("/r/n"); } else { printf(Msg); } //插入 SQL = "insert into vcaccesstest(ids,username,passwd,address) values(4,'我的','123210','测试地址')"; if(vspdctomysql->InsertData(SQL,Msg) == 0) printf("插入成功/r/n"); //更新 SQL = "update vcaccesstest set username = '修改了',passwd='2345' where ids = 3 "; if(vspdctomysql->UpdateData(SQL,Msg) == 0) printf("更新成功/r/n"); //删除 SQL = "delete from vcaccesstest where ids = 3 "; if(vspdctomysql->DeleteData(SQL,Msg) == 0) printf("删除成功/r/n"); vspdctomysql->CloseMySQLConn(); return 0; }
7、 数据库表确认表存在,(程序中的表和字段是我的数据库里面的内容,你要自己搞定你的SQL语句了,你可以看main函数里面的SQL变量的内容。
8、 编译,运行,一切ok。
9、 总结,你要做的事情很少了,两个主要的文件写好了,你看例子调用即可,其他MySQL的库文件和附加文件别人也为您准备好了,移植到其他系统也是很简单的,比如移植到Linux和Unix下也是很简单的,VspdCTOMySQL.h和VspdCTOMySQL.cpp基本上是采用标准的C++编写的,在别的系统可能需要做少量修改即可。
(二) 连接Mysql和从MySql中取出数据的部分API介绍
1. mysql_real_connect()
1) 函数原型
MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned int client_flag)
2) 参数及说明
• 第一个参数应该是一个现存MYSQL结构的地址。在调用mysql_real_connect()之前,你必须调用mysql_init()初始化MYSQL结构。见下面的例子。
• host值可以是一个主机名或一个IP地址。如果host是NULL或字符串”localhost”,假定是到本地主机的一个连接。如果OS支持套接字(Unix)或命名管道(Win32),使用他们而不是TCP/IP与服务器连接。
• user参数包含用户的MySQL登录ID。如果user是NULL,假定是当前用户。在Unix下,它是当前登录名。在Windows ODBC下,必须明确地指定当前用户名字。见16.4 怎样填写ODBC管理程序中各种域。
• passwd参数为user包含口令。如果passwd是NULL,只有在user表中对于有一个空白口令字段的用户的条目将被检查一个匹配。这允许数据库主管设置MySQL权限,使用户获得不同的口令,取决于他们是否已经指定一个口令。注意:不要试图在调用mysql_real_connect()前加密口令;口令加密自动被客户API处理。
• db是数据库名。如果db不是NULL,连接将缺省数据库设置为这个值。
• 如果port不是0,值对于TCP/IP连接将用作端口号。注意host参数决定连接的类型。
• 如果unix_socket不是NULL,字符串指定套接字或应该被使用的命名管道。注意host参数决定连接的类型。
• client_flag值通常是0,但是在很特殊的情况下可以被设置为下列标志的组合:
标志名字 意味着的标志
CLIENT_FOUND_ROWS 返回找到的(匹配的)行数,不是受到影响的行数。
CLIENT_NO_SCHEMA 不允许db_name.tbl_name.col_name语法。这是为了ODBC;如果你使用该语法,导致语法分析器产生一个错误,它是为在一些ODBC程序捕捉错误是有用。
CLIENT_COMPRESS 使用压缩协议。
CLIENT_ODBC 客户是一个ODBC客户。这使mysqld变得对ODBC更友好。
该函数用于连接数据库
3) 返回值
如果连接成功,一个 MYSQL*连接句柄。如果连接失败,NULL。对一个成功的连接,返回值与第一个参数值相同,除非你传递NULL给该参数。
4) 错误
CR_CONN_HOST_ERROR
不能连接MySQL服务器。
CR_CONNECTION_ERROR
不能连接本地MySQL服务器。
CR_IPSOCK_ERROR
不能创建一个IP套接字。
CR_OUT_OF_MEMORY
内存溢出。
CR_SOCKET_CREATE_ERROR
不能创建一个Unix套接字。
CR_UNKNOWN_HOST
不能找到主机名的IP地址。
CR_VERSION_ERROR
由于试图使用一个不同协议版本的一个客户库与一个服务器连接导致的一个协议失配。如果你使用一个非常老的客户库连接一个没有使用–old-protocol选项启动的新服务器,这就能发生。
CR_NAMEDPIPEOPEN_ERROR;
不能在 Win32 上创建一个命名管道。
CR_NAMEDPIPEWAIT_ERROR;
不能在 Win32 上等待一个命名管道。
CR_NAMEDPIPESETSTATE_ERROR;
不能在 Win32 上得到一个管道处理器。
2. mysql_select_db()
1) 函数原型
int mysql_select_db(MYSQL *mysql, const char *db)
2) 参数及说明
使得由db指定的数据库成为 在由mysql指定的连接上的缺省(当前)数据库。在随后的查询中,这个数据库对于不包括一个显式的数据库指定符的表的引用是缺省数据库。
除非连接的用户能被认证允许使用数据库,否则mysql_select_db()失败。
3) 返回值
成功,零。如果发生一个错误,非零。
4) 错误
CR_COMMANDS_OUT_OF_SYNC
命令以一个不适当的次序被执行。
CR_SERVER_GONE_ERROR
MySQL服务器关闭了。
CR_SERVER_LOST
对服务器的连接在查询期间失去。
CR_UNKNOWN_ERROR
发生一个未知的错误。
3. mysql_real_query
1) 函数原型
int mysql_real_query(MYSQL *mysql, const char *query, unsigned int length)
2) 参数及说明
执行由query指向的SQL查询,它应该是一个length个字节的字符串。查询必须由一个单个的SQL语句组成。你不应该在语句后增加一个终止的分号(“;”)或\g。
对于包含二进制数据的查询,你必须使用mysql_real_query()而不是mysql_query(),因为二进制代码数据可能包含“\0”字符,而且,mysql_real_query()比mysql_query()更快,因为它对查询字符串调用strlen()。
3) 返回值
如果查询成功,零。如果发生一个错误,非零。
4) 错误
CR_COMMANDS_OUT_OF_SYNC
命令以一个不适当的次序被执行。
CR_SERVER_GONE_ERROR
MySQL服务器关闭了。
CR_SERVER_LOST
对服务器的连接在查询期间失去。
CR_UNKNOWN_ERROR
发生一个未知的错误。
4. mysql_store_result
1) 函数原型
MYSQL_RES *mysql_store_result(MYSQL *mysql)
2) 参数及说明
用于将mysql_real_query查询结果返回
3) 返回值
返回MYSQL_RES结构,如果获取失败则返回空
5. mysql_fetch_row()
1) 函数原型
MYSQL_ROW *mysql_fetch_row(MYSQL_RES* res)
2) 参数及说明
用于读取MYSQL_RES
3) 返回值
返回表示MYSQL_RES的下一行的MYSQL_ROW