【项目组件】第三方库——MySQL CAPI
目录
前言
MySQL CAPI的功能
MySQL CAPI的接口
句柄初始化
连接MySQL服务器
设置当前字符集
选择操作数据库
执行SQL语句
保存查询结果到本地(获取结果集)
获取结果集中的行数
获取结果集中的列数
遍历结果集
释放结果集
关闭MySQL连接
获取错误原因
MySQL CAPI的使用
前言
注意:本文介绍不会涉及MySQL数据库,已经默认读者掌握了MySQL的增删查改SQL语句的基础上使用MySQL CAPI第三方库
MySQL CAPI的功能
mysql本质是c/s模式, 我们之前使用MySQL时都是通过连接mysqld,然后输入SQL语句的方式实现的数据库的增删查改
在我们实际项目中,不可能再像之前一样,直接连接数据库输入SQL语句,我们需要有一种方法可以让我们编写的代码执行特定的SQL语句!
MySQL CAPI提供了一种用C语言代码操作数据库的功能
MySQL CAPI的接口
MySQL CAPI所包含的头文件默认是:mysql/mysql.h
句柄初始化
使用MySQL API的各种操作,我们都需要创建一个操作句柄,MySQL API提供了如下接口初始化操作句柄:
MYSQL *mysql_init(MYSQL *mysql);
- mysql_init的功能是初始化一个操作句柄
- mysql_init的参数mysql若传递空的话,mysql_init函数内部在堆上申请一个句柄对象并返回。
- mysql_init若初始化句柄成功返回句柄指针,否则返回NULL
连接MySQL服务器
如下接口:
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 long client_flag);
- mysql:已完成初始化的句柄指针,此为输出型参数。后续所有使用句柄指针的操作,使用该参数变量
- host:主机号字符串。(MySQL可以支持远程连接,但需要通过特殊配置)
- user:登录用户字符串。
- passwd:登录密码字符串
- db:默认选择的数据库
- port:端口号,一般为3306
- unix_socket:通信管道文件或者socket文件,通常置为NULL
- client_flag:客户端标志位,通常置为0
- 返回值:若连接成功,返回句柄指针。否则返回NULL 。
设置当前字符集
如下接口:
int mysql_set_character_set(MYSQL *mysql, const char *csname)
- mysql:已完成初始化的句柄指针
- csname:字符集名称,通常是"utf8"
- 返回值:设置成功返回0,否则返回非0
选择操作数据库
如下接口:
int mysql_select_db(MYSQL *mysql, const char *db)
- mysql:已完成初始化的句柄指针
- db:要选择的数据库名
- 返回值:选择成功返回0,否则返回非0
执行SQL语句
如下接口:
int mysql_query(MYSQL *mysql, const char *stmt_str)
- mysql:已完成初始化的句柄指针
- stmt_str:要执行的SQL语句
- 返回值:执行成功返回0,否则返回非0
保存查询结果到本地(获取结果集)
如下接口:
MYSQL_RES *mysql_store_result(MYSQL *mysql)
- mysql:已完成初始化的句柄指针
- 返回值:若成功返回MYSQL_RES对象,该对象中保存的是查询结果信息,可以通过后续接口对结果进行操作。若失败返回NULL。(MYSQL_RES*对象我们称为结果集)
注意:返回的MYSQL_RES*对象是在堆上申请空间的,需要通过后续接口进行手动释放,否则会造成内存泄露
获取结果集中的行数
uint64_t mysql_num_rows(MYSQL_RES *result);
- 功能:查看result结果集的行数,也就是你通过select * from获取的信息行数/记录个数
获取结果集中的列数
unsigned int mysql_num_fields(MYSQL_RES *result)
- 功能:查看result结果集的列数。
遍历结果集
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
- 功能:用于遍历result结果集
- MYSQL_ROW:该类型是一个char**类型,它保存了一行数据记录的信息
注意:这个接⼝会保存当前读取结果位置,每次获取的都是下⼀条记录
如何遍历?
- 先使用该接口获取第一行记录
- 通过[i]的方式遍历获取第一行第i列数据
- 再次调用该接口获取第二行记录
- ...
释放结果集
void mysql_free_result(MYSQL_RES *result)
- result:待释放结果集
关闭MySQL连接
void mysql_close(MYSQL *mysql)
- 该接口完成了两个动作。释放mysql句柄指针和关闭mysql连接
- mysql:待释放句柄指针
获取错误原因
const char *mysql_error(MYSQL *mysql)
- 该接口用于获取mysql接口执行错误原因
- mysql:已初始化的句柄指针
- 返回值:错误信息
MySQL CAPI的使用
创建测试数据库和表
创建数据库的操作需要我们mysql连接数据库后通过SQL语句创建
create database if not exists test_db;
use test_db;
create table stu(
id int primary key auto_increment, -- 学⽣id
age int, -- 学⽣年龄
name varchar(32) -- 学⽣姓名
);
使用MySQL CAPI完成数据库的增删改操作
要使用MySQL CAPI完成数据库的增删改所有操作,那么我们大致分为六步:
- 初始化mysql句柄
- 连接服务器
- 设置客户端字符集
- 选择要操作的数据库
- 执行SQL语句
- 关闭连接
#include <iostream>
#include <mysql/mysql.h>
#include <string>
#define HOST "127.0.0.1"
#define USER "root"
#define PASSWD ""
#define DB "test_db"
#define PORT 3306
int main()
{
// 初始化mysql句柄
MYSQL* mysql = mysql_init(nullptr);
// 连接服务器
if(mysql_real_connect(mysql,HOST,USER,PASSWD,DB,PORT,nullptr,0) == nullptr)
{
printf("connect mysql server failed: %s\n",mysql_errno(mysql));
mysql_close(mysql);
return -1;
}
// 设置客户端字符集
if(mysql_set_character_set(mysql,"utf8") != 0)
{
printf("set mysql client character_set error: %s\n",mysql_errno(mysql));
mysql_close(mysql);
return -1;
}
// 选择要操作的数据库
//由于我们在连接数据库时的默认选择数据库就是test_db,无需再次选择
//执行SQL语句
std::string ins = "insert into stu ";
if(mysql_query(mysql,(ins + "values(null,18,'张三')").c_str()) != 0)
{
printf("ins error: %s\n",mysql_errno(mysql));
mysql_close(mysql);
return -1;
}
mysql_close(mysql);
return 0;
}
上述执行SQL语句只展示了增加,对于删除和修改时的步骤都是类似的!
注意:编译时由于MySQL CAPI所在的路径不在/usr/include下,它在/usr/lib64/mysql/下。所以我们需要通过-L指定库文件所在路径,同时链接的库名为mysqlclient
g++ -o test Main.cc -std=c++11 -L/usr/lib64/mysql/ -lmysqlclient
使用MySQL CAPI完成数据库的查找
完成数据库查找时的步骤与增删改时的步骤都差不多,它们之间的区别是在执行SQL语句后的动作!
MySQL CAPI完成数据库查找的步骤:
- ...
- 执行SQL查询语句
- 保存结果到本地结果集中
- 获取结果集中的结果条数
- 遍历保存好的结果集
- 释放结果集
- 关闭连接
#include <iostream>
#include <mysql/mysql.h>
#include <string>
#define HOST "127.0.0.1"
#define USER "root"
#define PASSWD ""
#define DB "test_db"
#define PORT 3306
int main()
{
// 初始化mysql句柄
MYSQL* mysql = mysql_init(nullptr);
// 连接服务器
if(mysql_real_connect(mysql,HOST,USER,PASSWD,DB,PORT,nullptr,0) == nullptr)
{
printf("connect mysql server failed: %s\n",mysql_errno(mysql));
mysql_close(mysql);
return -1;
}
// 设置客户端字符集
if(mysql_set_character_set(mysql,"utf8") != 0)
{
printf("set mysql client character_set error: %s\n",mysql_errno(mysql));
mysql_close(mysql);
return -1;
}
// 选择要操作的数据库
//由于我们在连接数据库时的默认选择数据库就是test_db,无需再次选择
//执行SQL插入语句,插入三条记录
if(mysql_query(mysql,"insert into stu values(null,18,'张三')") != 0)
{
printf("ins error: %s\n",mysql_errno(mysql));
mysql_close(mysql);
return -1;
}
if(mysql_query(mysql,"insert into stu values(null,19,'李四')") != 0)
{
printf("ins error: %s\n",mysql_errno(mysql));
mysql_close(mysql);
return -1;
}
if(mysql_query(mysql,"insert into stu values(null,20,'王五')") != 0)
{
printf("ins error: %s\n",mysql_errno(mysql));
mysql_close(mysql);
return -1;
}
//之后是查询的步骤
//执行SQL查询语句
if(mysql_query(mysql,"select * from stu") != 0)
{
printf("sel error: %s\n",mysql_errno(mysql));
mysql_close(mysql);
return -1;
}
//保存结果到本地结果集中
MYSQL_RES* res = mysql_store_result(mysql);
if(res == nullptr)
{
mysql_close(mysql);
return -1;
}
//获取结果集的行列数
int num_row = mysql_num_rows(res);
int num_col = mysql_num_fields(res);
//遍历保存好的结果集
for(int i = 0 ; i < num_row ; ++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
for(int j = 0 ; j < num_col ; ++j)
{
std::cout << row[j] << " ";
}
std::cout << std::endl;
}
//释放结果集
mysql_free_result(res);
//关闭连接
mysql_close(mysql);
return 0;
}