1. Linux平台准备
(1)安装SDK开发包的命令
sudo apt-get install libmysqlclient-dev
(2)编译时需要链接的库:-lmysqlclient
2. mysql 的初始化和清理
#include <mysql/mysql.h>
MYSQL mysql1; //创建句柄
mysql_init(&mysql1); //初始化句柄
mysql_close(&mysql); //关闭句柄
3. mysql 的连接登录
(1)连接登录 mysql_real_connect
const char *p = "192.168.126.215"; //配置ip
const char *user = "root"; //配置用户名
const char *password" = "123456"; //配置密码
const char *db = "test"; //配置要打开的数据库if ( mysql_real_connect(&mysql1, ip, user, password, db, 13306, nullptr, 0) == 0) //等于0则打开失败
{cout<<"connect error"<<endl;
}
else
{cout<<"connect ok"<<endl;
}
(2)设置断开自动重连
//设置断开重连的功能
int ret = 1;
mysql_options(&mysql1, MYSQL_OPT_RECONNECT, &ret);
//中间的宏表示如果发现连接丢失,则启动与服务器的自动再连接;//设置自动检测的超时时间
int timeout = 3;
mysql_options(&mysql1, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
//中间的宏表示以秒为单位的连接超时,即超过3秒就启动重新连接//设置是否连接的检测
if( mysql_ping(&mysql1) != 0 )
{cout<<"connect failed"<<endl;
}
else
{cout<<"connect success"<<endl;
}
4. mysql 的数据查询
(1)执行sql语句,注意:执行sql语句后,必须获取结果集并且清理;
//创建表
string sql = "create table person(id int, name varchar(20), age int";
mysql_real_query(&mysql, sql.c_str(), sql.size());
//mysql_query(&mysql, sql.c_str()); 和上面不同的是,这里并没有指定长度,执行效率没有上面的快
//对于包含二进制数据的查询,必须使用mysql_real_query(),因为二进制代码数据可能包含‘\0’字符;//插入数据
string sql2 = "insert into person(id, name, age)values(1, 'zhangsan', 14);
mysql_real_query(&mysql, sql2.c_str(), sql2.size());//查询数据
string sql3 = "select * from person";
mysql_real_query(&mysql, sql3.c_str(), sql3.size());
(2)获取结果集
//获取结果集
MYSQL_RES *result; //定义一个MYSQL_RES结构;
result = mysql_use_result(&mysql1); //将查询结构保存在result中;
if(result == nullptr)
{cout<<"select error"<<endl;
}//获取字段个数,即查询获得的结果里有几列数据
int nums = 0;
nums = mysql_num_fields(result); //属于表结构的获取//获取字段名,即列的名称
MYSQL_FIELD * fields; //字段名的数据类型的变量
fields = mysql_fetch_fields(result); //属于表结构的获取
for(int i = 0; i < num; i++)
{cout<<fields[i].name<<"|";
}
cout<<endl;//遍历显示结果
MYSQL_ROW row; //存储每一行数据的数据类型的变量
while( (row = mysql_fetch_row(result)) != nullptr) //mysql_fetch_row()函数从指定的结果集中获取一行数据返回给row,是数组的形式,即row内部是字符串数组指针(二级指针)
{for(i = 0; i < nums; i++){cout<<row[i]<<"|";}cout<<endl;
}
(3)清理结果集
//释放结果集的指针空间
mysql_free_result(result);
整体示例如下:
#include <iostream>
#include <mysql/mysql.h>
#include <unistd.h>using namespace std;int main(int argc, char **argv)
{MYSQL mysql1;mysql_init(&mysql1);const char *ip = "192.168.226.128";const char *user = "root";const char *password = "123456";const char *db = "test";if(mysql_real_connect(&mysql1, ip, user, password, db, 13306, nullptr,0) == 0){cout<<"connect error"<<endl;}else{cout<<"connect ok"<<endl;}string sql = "create table person(id int, name varchar(20), age int)";mysql_real_query(&mysql1, sql.c_str(), sql.size());// string sql1 = "select"int ret = 1;mysql_options(&mysql1, MYSQL_OPT_RECONNECT, &ret);int timeout = 3;mysql_options(&mysql1, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);// while(1) //测试断开重连功能// {// if(mysql_ping(&mysql1) != 0)// {// cout<<"connect failed"<<endl;// }// else// {// // cout<<"connnect ok"<<endl;// }// sleep(1);// }string sql2 = "insert into person(id, name, age)values(1,'zhangsan',12)";mysql_real_query(&mysql1, sql2.c_str(), sql2.size());string sql22 = "insert into person(id, name, age)values(2,'lisi',16)";mysql_real_query(&mysql1, sql22.c_str(), sql22.size());string sql3 = "select * from person";mysql_real_query(&mysql1, sql3.c_str(), sql3.size());MYSQL_RES * result = mysql_use_result(&mysql1);if(result == nullptr){cout<<"select error"<<endl;}int nums = 0;nums = mysql_num_fields(result);cout<<"nums = "<<nums<<endl;MYSQL_FIELD * fields = mysql_fetch_fields(result);for(int i = 0; i < nums; i++){cout<<fields[i].name<<"|";}cout<<endl;MYSQL_ROW row;while((row = mysql_fetch_row(result)) != nullptr){for(int i =0; i < nums; i++){cout<<row[i]<<"|";}cout<<endl;}mysql_free_result(result);mysql_close(&mysql1);return 0;
}
运行结果如下:
5. mysql 显示中文
//设置中文的思路是统一设置字符集为utf8;
const char * csname = "utf8";
mysql_set_character_set(&mysql, csname);
6. 图片存储与读取保存的例子
#include <iostream>
#include <mysql/mysql.h>
#include <thread>
#include <string>
#include <sstream>
#include <map>
#include <chrono>
#include <fstream>
using namespace std;
using namespace chrono;int main()
{//初始化mysql上下文MYSQL mysql;//单线程模式 mysql_init自动调用 mysql_library_init 线程不安全mysql_init(&mysql);const char* host = "192.168.226.128";//const char *host = "192.168.0.203";const char* user = "root";const char* pass = "123456";const char* db = "test"; //数据库名称//CLIENT_MULTI_STATEMENTS 支持多条sql语句if (!mysql_real_connect(&mysql, host, user, pass, db, 13306, 0, CLIENT_MULTI_STATEMENTS))//if (!mysql_real_connect(&mysql, host, user, pass, db, 3306, 0, 0)){cout << "mysql connect failed!" << mysql_error(&mysql) << endl;}else{cout << "mysql connect success!" << endl;}string sql = "";//1 创建好存放二进制数据的表 t_datasql = "CREATE TABLE IF NOT EXISTS `t_data` (\`id` int AUTO_INCREMENT,\`name` varchar(1024),\`data` blob,\`size` int,\PRIMARY KEY(`id`))";int re = mysql_query(&mysql, sql.c_str());if (re != 0){cout << mysql_error(&mysql) << endl;}//2 清空表 truncate t_datasql = "truncate t_data";re = mysql_query(&mysql, sql.c_str());if (re != 0){cerr << mysql_error(&mysql) << endl;}//3 初始化stmt mysql_stmt_initMYSQL_STMT* stmt = mysql_stmt_init(&mysql);if (!stmt){cerr << "mysql_stmt_init failed!" << mysql_error(&mysql) << endl;}//4 预处理sql语句sql = "INSERT INTO `t_data` (name,data,size) VALUES(?,?,?)";if (mysql_stmt_prepare(stmt, sql.c_str(), sql.size())){cerr << "mysql_stmt_prepare failed!" << mysql_stmt_error(stmt) << endl;}//5 打开并读取文件string path = ".//";string filename = "mysql.jpg";cout << path + filename << endl;//读取二进制fstream in(path + filename, ios::in | ios::binary);if (!in.is_open()){cerr << "file " << filename << " open failed!" << endl;}//文件指针移动到结尾处in.seekg(0, ios::end);//文件大小和文件二进制地址int filesize = in.tellg();//回到开头in.seekg(0, ios::beg);char* data = new char[filesize];int readed = 0; //已经读了多少while (!in.eof()){in.read(data + readed, filesize - readed);//读取了多少字节if (in.gcount() <= 0)break;readed += in.gcount();}in.close();//6 绑定字段MYSQL_BIND bind[3] = { 0 };bind[0].buffer_type = MYSQL_TYPE_STRING; //name 文件名bind[0].buffer = (char*)filename.c_str();bind[0].buffer_length = filename.size();bind[1].buffer_type = MYSQL_TYPE_BLOB; //data 文件二进制内容bind[1].buffer = data; //二进制文件bind[1].buffer_length = filesize;//文件大小bind[2].buffer_type = MYSQL_TYPE_LONG;bind[2].buffer = &filesize;if (mysql_stmt_bind_param(stmt, bind) != 0){cerr << "mysql_stmt_bind_param failed! " << mysql_stmt_error(stmt) << endl;}//7 执行stmt sqlif (mysql_stmt_execute(stmt) != 0){cerr << "mysql_stmt_execute failed! " << mysql_stmt_error(stmt) << endl;}delete data;mysql_stmt_close(stmt);sql = "select * from t_data";re = mysql_query(&mysql, sql.c_str());if (re != 0){cerr << "mysql query failed!" << mysql_error(&mysql) << endl;}//获取结果集MYSQL_RES* res = mysql_store_result(&mysql);if (!res){cerr << "mysql_store_result failed!" << mysql_error(&mysql) << endl;}//取一行数据MYSQL_ROW row = mysql_fetch_row(res);if (!row){cerr << "mysql_fetch_row failed!" << mysql_error(&mysql) << endl;}cout << row[0] << " " << row[1] << " " << row[3] << endl;//获取每列数据的大小unsigned long* lens = mysql_fetch_lengths(res);int fnum = mysql_num_fields(res);for (int i = 0; i < fnum; i++){cout << "[" << lens[i] << "]";}filename = "out_";filename += row[1];fstream out(filename, ios::out | ios::binary);if (!out.is_open()){cerr << "open file " << filename << " failed!" << endl;}out.write(row[2], lens[2]);out.close();mysql_close(&mysql);mysql_library_end();std::cout << "Mysql 8.0 API!\n";mysql_close(&mysql);mysql_library_end();std::cout << "Mysql 8.0 API!\n";getchar();
}