文章目录
- [1. 安装 MySQL 库](#1. 安装 MySQL 库)
-
- [1.1 官网下载](#1.1 官网下载)
- [1.2 通过 yum 安装开发环境](#1.2 通过 yum 安装开发环境)
- [2. 连接 MySQL](#2. 连接 MySQL)
- [3. MySQL 接口介绍](#3. MySQL 接口介绍)
-
- [3.1 初始化 mysql_init()](#3.1 初始化 mysql_init())
- [3.2 链接数据库 mysql_real_connect](#3.2 链接数据库 mysql_real_connect)
- [3.3 下发mysql命令 mysql_query](#3.3 下发mysql命令 mysql_query)
-
- [3.3.1 解决插入中文的乱码问题](#3.3.1 解决插入中文的乱码问题)
- [3.4 获取执行结果 mysql_store_result](#3.4 获取执行结果 mysql_store_result)
- [3.5 获取结果行数 mysql_num_rows](#3.5 获取结果行数 mysql_num_rows)
- [3.6 获取结果列数 mysql_num_fields](#3.6 获取结果列数 mysql_num_fields)
- [3.7 获取列名 mysql_fetch_fields](#3.7 获取列名 mysql_fetch_fields)
- [3.8 获取结果内容 mysql_fetch_row](#3.8 获取结果内容 mysql_fetch_row)
- [3.9 释放执行结果 mysql_free_result](#3.9 释放执行结果 mysql_free_result)
- [3.10 关闭mysql连接 mysql_close](#3.10 关闭mysql连接 mysql_close)
- [3.11 事务常用操作](#3.11 事务常用操作)
-
- [3.11.1 设置自动提交模式 mysql_autocommit](#3.11.1 设置自动提交模式 mysql_autocommit)
- [3.11.2 提交当前事务 mysql_commit](#3.11.2 提交当前事务 mysql_commit)
- [3.11.3 用于回滚当前事务 mysql_rollback](#3.11.3 用于回滚当前事务 mysql_rollback)
我们新建一个 edison 用户专门用来做 C/C++ 的测试。
sql
# 创建用户
create user 'edison'@'localhost' identified by 'QAZwsxedc123456.';
# 查看用户表
select user,host,authentication_string from user;
# 刷新权限
flush privileges;
结果如下:

然后创建一个名为 ai_study_data 的数据库,并赋予 edison 用户对该数据库的所有权限:
sql
# 建库
create database ai_study_data;
# 赋予权限
grant all on ai_study_data.* to 'edison'@'localhost';
# 刷新权限
flush privileges;
此时,当我们用 edison 用户登录以后,就可以看到 root 用户创建的数据库了

1. 安装 MySQL 库
这里提供两种做法,一是去官网下载,二是通过 yum 源安装。
1.1 官网下载
要使用 C/C++ 语言连接 MySQL,需要使用 MySQL 官网提供的库,可以去 官网 下载

然后点击箭头指向的【Connector/C++】

选择默认的 Connector/C++ 9.5.0 下载即可。

1.2 通过 yum 安装开发环境
但是咱们今天不推荐上面这种做法。
因为当初我们在安装 MySQL 的时候,执行的是下面这两条命令,实际上它已经把我们需要用到的【开发工具】给我们已经安装好了
sql
# 安装MySQL客户端和服务器
[root@vm-centos:~]# yum install -y mysql-community-server
# 安装MySQL开发环境
[root@vm-centos:~]# yum install -y mysql-community-devel
注意:如果你第一次没有安装开发工具的话,需要去执行一下安装MySQL开发环境的命令。
其中 include 包含所有的方法声明,lib 包含所有的方法实现(打包成库)
bash
[root@vm-centos:~]# ls /usr/include/mysql/
[root@vm-centos:~]# ls /lib64/mysql/libmysql*
如下所示:

其中:libmysqlclient.a 是一个静态库,libmysqlclient.so 是一个动态库,这两个库是和 /usr/include/mysql/ 目录下的头文件搭配使用的,可以让我们通过代码访问并连接到数据库。
2. 连接 MySQL
先尝试连接一下 MySQL Client,通过 mysql_get_client_info() 函数,来验证我们的引入是否成功。
编写 test.cc 函数
cpp
#include <iostream>
#include <mysql/mysql.h>
using namespace std;
int main()
{
cout << "mysql client Version: " << mysql_get_client_info() << endl;
return 0;
}
当你在 VSCode 中引入头文件,如果给你自动提示时,说明引入成功了

编写 Makefile
bash
test:test.cc
g++ -o $@ $^ -L/lib64/mysql -lmysqlclient -std=c++11
.PHONY:clean
clean:
rm -f test
然后运行可执行文件 ./test 即可看到对应的 MySQL 版本:

其中:
-L/lib64/mysql: 这个选项指定了编译器搜索库文件的路径,/lib64/mysql是 MySQL 客户端库所在的目录。编译器会在这个目录下查找所需的库文件。-lmysqlclient: 这个选项告诉编译器将libmysqlclient库链接到程序中。libmysqlclient是 MySQL 的客户端库,包含了与 MySQL 服务器进行交互所需的函数。
至此引入库的工作已经做完,接下来就是熟悉接口。
3. MySQL 接口介绍
在 MySQL 5.7 C API Developer Guide 上有关于 MySQL 的各种 API 接口,写的很全很详细,下面主要介绍一下常用的接口。
3.1 初始化 mysql_init()
要使用库,必须先进行初始化。
mysql_init() 是用于初始化一个 MySQL 连接句柄的函数。
c
MYSQL *mysql_init(MYSQL *mysql);
参数:
- mysql:这是一个指向 MYSQL 结构体的指针,表示要初始化的 MySQL 连接句柄。如果传入 NULL,
mysql_init()会自动为你分配内存。
返回值:
- 如果初始化成功,返回一个指向 MYSQL 对象的指针。
- 如果初始化失败,返回 NULL。
代码示例:
cpp
int main()
{
MYSQL *myfd = mysql_init(nullptr);
if (nullptr == myfd)
{
cerr << "init MySQL error" << endl;
return 1;
}
cout << "init MySQL Success" << endl;
mysql_close(myfd);
return 0;
}
结果如下:

3.2 链接数据库 mysql_real_connect
初始化完毕之后,必须先链接数据库,在进行后续操作(MySQL 网络部分是基于 TCP/IP 的)。
mysql_real_connect() 是用于实际建立与 MySQL 数据库服务器连接的函数。它使用指定的参数进行连接,并返回一个有效的 MySQL 连接句柄。
c
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:一个指向
MYSQL对象的指针,该对象需要先通过mysql_init()初始化。用于指定要连接的 MySQL 连接句柄。 - host:数据库服务器的主机名或 IP 地址。如果连接本地数据库,可以使用
"localhost"或"127.0.0.1",也可以使用 UNIX 套接字文件路径(如果适用)。 - user:数据库用户名,用于连接数据库的身份验证。
- passwd:对应数据库用户的密码。
- db:需要连接的数据库名称。如果连接成功,之后可以在该数据库中执行查询等操作。如果不想指定特定数据库,可以传入
NULL。 - port:MySQL 服务器的端口号,通常是
3306。如果使用 UNIX 套接字连接,此参数可以设置为0。 - unix_socket:指定 UNIX 套接字文件的路径(如果连接到本地 MySQL 服务器并使用 UNIX 套接字)。如果不使用套接字连接,可以传入
NULL。 - client_flag:用于设置客户端连接的标志位。通常设置为
0,但可以使用一些选项(如CLIENT_COMPRESS等)来改变连接的行为。
返回值:
- 如果连接成功,返回指向
MYSQL连接对象的指针。 - 如果连接失败,返回
NULL,并且可以通过mysql_error()获取详细的错误信息。
代码示例:
cpp
// 下面的内容是在MySQL中创建的edison用户和测试数据库的信息
const string host = "127.0.0.1";
const string user = "edison";
const string passwd = "QAZwsxedc123456.";
const string db = "ai_study_data";
const unsigned int port = 3306;
int main()
{
MYSQL *myfd = mysql_init(nullptr);
if (nullptr == myfd)
{
cerr << "init MySQL error" << endl;
return 1;
}
cout << "init MySQL Success" << endl;
// 连接
if (nullptr == mysql_real_connect(myfd, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
{
cerr << "connect MySQL error" << endl;
return 2;
}
cout << "connect MySQL Success" << endl;
mysql_close(myfd);
return 0;
}
结果如下:

另外,我们可以在 MySQL 内部查看是否连接成功:

3.3 下发mysql命令 mysql_query
mysql_query() 是用于执行 SQL 查询的函数。
c
int mysql_query(MYSQL *mysql, const char *q);
参数说明:
- mysql:一个指向
MYSQL对象的指针,表示已经建立的 MySQL 连接。 - q:一个指向包含 SQL 查询语句的字符串。此字符串可以是任何有效的 SQL 查询,如
SELECT,INSERT,UPDATE,DELETE等。
返回值:
- 0:查询成功执行。
- 非 0 值:查询执行失败,错误代码可以通过
mysql_error()获取。
在编写代码前,我们先以 edison 用户的身份在 ai_study_data 数据库中建一张表
sql
create table if not exists user(
id bigint primary key auto_increment,
name varchar(32) not null,
age int not null,
telephone varchar(32) unique
);
结果如下:

代码示例:
cpp
int main()
{
MYSQL *myfd = mysql_init(nullptr);
if (nullptr == myfd)
{
cerr << "init MySQL error" << endl;
return 1;
}
cout << "init MySQL Success" << endl;
// 连接
if (nullptr == mysql_real_connect(myfd, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
{
cerr << "connect MySQL error" << endl;
return 2;
}
cout << "connect MySQL Success" << endl;
// 下达指令
string sql; // 定义sql语句
while (true) // 模拟一个MySQL命令行操作
{
cout << "mysql> ";
if (!getline(cin, sql) || sql == "quit")
{
cout << "Bye bye" << endl;
break;
}
int n = mysql_query(myfd, sql.c_str());
if (0 == n)
cout << "[" << sql << "] Operation success" << endl;
else
cerr << "Operation failed: " << n << endl;
}
mysql_close(myfd);
return 0;
}
结果如下(在 C/C++ 里面编写 sql 的时候,可以不用带 ; 号):

但是,一情况下,在 C/C++ 调用 MySQL 的时候,不会是上面那种用法,而是直接帮我们执行 sql 语句即可。
代码示例:
cpp
int main()
{
MYSQL *myfd = mysql_init(nullptr);
if (nullptr == myfd)
{
cerr << "init MySQL error" << endl;
return 1;
}
cout << "init MySQL Success" << endl;
// 连接
if (nullptr == mysql_real_connect(myfd, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
{
cerr << "connect MySQL error" << endl;
return 2;
}
cout << "connect MySQL Success" << endl;
string sql = "update user set name='Jimmy' where id = 2"; // 定义sql语句
int n = mysql_query(myfd, sql.c_str());
if (0 == n)
cout << "Operation success" << endl;
else
cerr << "Operation failed" << endl;
// 关闭连接
mysql_close(myfd);
return 0;
}
结果如下:

同样,还可以进行插入操作
sql
string sql = "insert into user (name, age, telephone) values ('Andy', 19, '987654321')";
int n = mysql_query(myfd, sql.c_str());
if (0 == n)
cout << "Operation success" << endl;
else
cerr << "Operation failed" << endl;
结果如下:

那么删除操作也是一样:
cpp
string sql = "delete from user where id = 1";
int n = mysql_query(myfd, sql.c_str());
if (0 == n)
cout << "Operation success" << endl;
else
cerr << "Operation failed" << endl;
结果如下:

3.3.1 解决插入中文的乱码问题
如果我们执行插入中文字符的 sql 语句会怎么样呢?
cpp
string sql = "insert into user (name, age, telephone) values ('张三', 20, '555333999')";
int n = mysql_query(myfd, sql.c_str());
if (0 == n)
cout << "Operation success" << endl;
else
cerr << "Operation failed" << endl;
结果如下:

可以看到,获取英文没有问题,但是获取中文却是乱码,那么我们需要设置连接的默认字符集是 utf8(原始默认的是 latin1)。
cpp
mysql_set_character_set(myfd, "utf8");
再次插入带中文字符的 sql
cpp
int main()
{
MYSQL *myfd = mysql_init(nullptr);
if (nullptr == myfd)
{
cerr << "init MySQL error" << endl;
return 1;
}
cout << "init MySQL Success" << endl;
// 连接
if (nullptr == mysql_real_connect(myfd, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
{
cerr << "connect MySQL error" << endl;
return 2;
}
mysql_set_character_set(myfd, "utf8"); // 设置连接字符
cout << "connect MySQL Success" << endl;
string sql = "insert into user (name, age, telephone) values ('王五', 21, '111222333')";
int n = mysql_query(myfd, sql.c_str());
if (0 == n)
cout << "Operation success" << endl;
else
cerr << "Operation failed" << endl;
// 关闭连接
mysql_close(myfd);
return 0;
}
可以看到能够支持中文字符了

(记得把乱码的记录给删除掉)
3.4 获取执行结果 mysql_store_result
编写的 sql 执行完以后,如果是查询语句,我们当然还要读取数据,如果 update / insert 等语句,那么就只需要看下操作成功与否即可。 如果 mysql_query 返回成功,那么我们就通过下面这个函数来读取结果。
mysql_store_result() 是用于检索 SQL 查询结果集的函数。
c
MYSQL_RES *mysql_store_result(MYSQL *mysql);
参数说明:
- mysql:一个指向
MYSQL对象的指针,表示已经建立的 MySQL 连接。
返回值:
- 返回一个指向
MYSQL_RES结果集的指针。 - 如果查询没有结果或发生错误,返回
NULL。
代码示例:
cpp
// 获取查询到的结果集
MYSQL_RES *res = mysql_store_result(myfd);
if (nullptr == res)
{
cerr << "mysql store result failed" << endl;
return 4;
}
3.5 获取结果行数 mysql_num_rows
mysql_num_rows() 是用于获取查询结果集中的行数的函数。
c
my_ulonglong mysql_num_rows(MYSQL_RES *res);
参数说明:
- res:一个指向
MYSQL_RES结构体的指针,表示查询结果集。
返回值:
- 返回结果集中的行数。
- 如果查询失败或没有返回任何行,返回
0。
3.6 获取结果列数 mysql_num_fields
mysql_num_fields() 是用于获取查询结果集中的列数的函数。
c
unsigned int mysql_num_fields(MYSQL_RES *res);
参数说明:
- res:一个指向
MYSQL_RES结构体的指针,表示查询结果集。
返回值:
- 返回结果集中的列数。
- 如果查询失败或没有返回任何列,返回
0。
接下来,我们可以通过上面两个函数来打印验证结果集中的【行 / 列】。
代码示例:
cpp
int main()
{
MYSQL *myfd = mysql_init(nullptr);
if (nullptr == myfd)
{
cerr << "init MySQL error" << endl;
return 1;
}
cout << "init MySQL Success" << endl;
// 连接
if (nullptr == mysql_real_connect(myfd, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
{
cerr << "connect MySQL error" << endl;
return 2;
}
mysql_set_character_set(myfd, "utf8");
cout << "connect MySQL Success" << endl;
// 操作mysql
string sql = "select * from user";
int n = mysql_query(myfd, sql.c_str());
if (0 == n)
cout << "Operation success" << endl;
else
{
cerr << "Operation failed" << endl;
return 3;
}
// 获取查询到的结果集
MYSQL_RES * res = mysql_store_result(myfd);
if (nullptr == res)
{
cerr << "mysql store result failed" << endl;
return 4;
}
//
int rows = mysql_num_rows(res);
int fields = mysql_num_fields(res);
cout << "行: " << rows << endl;
cout << "列: " << fields << endl;
// 关闭连接
mysql_close(myfd);
return 0;
}
结果如下:

3.7 获取列名 mysql_fetch_fields
mysql_fetch_fields() 是用于获取查询结果集中的所有列信息的函数。
c
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);
参数说明:
- res:一个指向
MYSQL_RES结构体的指针,表示查询结果集。
返回值:
- 返回一个指向
MYSQL_FIELD结构体数组的指针,数组中的每个元素表示结果集中的一列。 - 如果查询失败或没有列,返回
NULL。
提取结果集中的列属性(其实就是打印 user 表中每一列的名称)代码示例:
cpp
int main()
{
MYSQL *myfd = mysql_init(nullptr);
if (nullptr == myfd)
{
cerr << "init MySQL error" << endl;
return 1;
}
cout << "init MySQL Success" << endl;
// 连接
if (nullptr == mysql_real_connect(myfd, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
{
cerr << "connect MySQL error" << endl;
return 2;
}
mysql_set_character_set(myfd, "utf8");
cout << "connect MySQL Success" << endl;
// 对表执行查询操作
string sql = "select * from user";
int n = mysql_query(myfd, sql.c_str());
if (0 == n)
cout << "Operation success" << endl;
else
{
cerr << "Operation failed" << endl;
return 3;
}
// 获取查询到的结果集
MYSQL_RES * res = mysql_store_result(myfd);
if (nullptr == res)
{
cerr << "mysql store result failed" << endl;
return 4;
}
// 下面全是对res结果集进行操作
int rows = mysql_num_rows(res);
int fields = mysql_num_fields(res);
cout << "行: " << rows << endl;
cout << "列: " << fields << endl;
// 获取表的属性
MYSQL_FIELD *fields_array = mysql_fetch_fields(res);
for (int i = 0; i < fields; i ++)
{
cout << fields_array[i].name << "\t";
}
cout << "\n";
// 关闭连接
mysql_close(myfd);
return 0;
}
可以看到,此时就打印出了表中每一列的名称:

另外,还可以通过下面的代码,来查看我们当前用的是哪个数据库,以及库里面的哪张表?
cpp
cout << fields_array[0].db << " : " << fields_array[0].table << endl;
结果如下:

3.8 获取结果内容 mysql_fetch_row
mysql_fetch_row() 是用于从查询结果集中获取一行数据的函数。
c
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
参数说明:
- result:一个指向
MYSQL_RES结构体的指针,表示查询结果集。
返回值:
- 返回一个
MYSQL_ROW类型的指针,表示结果集中的一行数据。每一行数据是一个字符串数组,数组中的每个元素对应一列的值。 - 如果没有更多的行或查询失败,返回
NULL。
提取结果集中每一行的内容(其实就是打印 user 表中所有的数据),代码示例:
cpp
int main()
{
MYSQL *myfd = mysql_init(nullptr);
if (nullptr == myfd)
{
cerr << "init MySQL error" << endl;
return 1;
}
cout << "init MySQL Success" << endl;
// 连接
if (nullptr == mysql_real_connect(myfd, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0))
{
cerr << "connect MySQL error" << endl;
return 2;
}
mysql_set_character_set(myfd, "utf8");
cout << "connect MySQL Success" << endl;
string sql = "select * from user";
int n = mysql_query(myfd, sql.c_str());
if (0 == n)
cout << "Operation success" << endl;
else
{
cerr << "Operation failed" << endl;
return 3;
}
// 获取查询到的结果集
MYSQL_RES * res = mysql_store_result(myfd);
if (nullptr == res)
{
cerr << "mysql store result failed" << endl;
return 4;
}
// 下面全是对res结果集进行操作
int rows = mysql_num_rows(res);
int fields = mysql_num_fields(res);
cout << "行: " << rows << endl;
cout << "列: " << fields << endl;
//
for (int i = 0; i < rows; i ++)
{
MYSQL_ROW row = mysql_fetch_row(res); // 每一行的数据
for (int j = 0; j < fields; j ++)
{
cout << row[j] << "\t";
}
cout << endl;
}
// 关闭连接
mysql_close(myfd);
return 0;
}
可以看到,此时就能拿到表的属性(每一列的名称)和所有数据了:

3.9 释放执行结果 mysql_free_result
mysql_free_result() 是用于释放由 mysql_store_result() 或 mysql_use_result() 获取的结果集的函数。
c
void mysql_free_result(MYSQL_RES *result);
参数说明:
- result:一个指向
MYSQL_RES结构体的指针,表示要释放的查询结果集。
返回值:
- 无返回值。
代码示例:
cpp
// 释放结果集res
mysql_free_result(res);
3.10 关闭mysql连接 mysql_close
mysql_close() 是用于关闭 MySQL 连接的函数。它释放与 MySQL 连接相关的资源并关闭连接。
cpp
void mysql_close(MYSQL *sock);
参数:
sock:这是一个指向已建立的 MYSQL 连接的指针,表示要关闭的 MySQL 连接。该指针通常是通过mysql_init()和mysql_real_connect()创建的连接。
返回值:
- 该函数没有返回值。
3.11 事务常用操作
mysql_autocommit()、mysql_commit() 和 mysql_rollback() 是用于事务管理的函数。
3.11.1 设置自动提交模式 mysql_autocommit
c
my_bool STDCALL mysql_autocommit(MYSQL *mysql, my_bool auto_mode);
参数说明:
- mysql:一个指向
MYSQL对象的指针,表示已建立的 MySQL 连接。 - auto_mode:一个布尔值,表示是否启用自动提交模式。如果为
TRUE,则每个 SQL 语句都会自动提交;如果为FALSE,则需要显式调用mysql_commit()或mysql_rollback()来提交或回滚事务。
返回值:
- 如果设置成功,返回
TRUE。 - 如果失败,返回
FALSE。
3.11.2 提交当前事务 mysql_commit
c
my_bool STDCALL mysql_commit(MYSQL *mysql);
参数说明:
- mysql:一个指向
MYSQL对象的指针,表示已建立的 MySQL 连接。
返回值:
- 如果提交成功,返回
TRUE。 - 如果失败,返回
FALSE。
3.11.3 用于回滚当前事务 mysql_rollback
c
my_bool STDCALL mysql_rollback(MYSQL *mysql);
参数说明:
- mysql:一个指向
MYSQL对象的指针,表示已建立的 MySQL 连接。
返回值:
- 如果回滚成功,返回
TRUE。 - 如果失败,返回
FALSE。