MYSQL访问之如何使用C/C++连接数据库

 更新时间:2026年05月28日 10:19:54   作者:埃伊蟹黄面  
本文详细介绍了使用C/C++访问MySQL数据库的方法,包括初始化连接、执行SQL语句和获取查询结果等内容,并强调了连接池的使用以提高性能和资源利用率,感兴趣的朋友一起看看吧

1. 前言

我们已经学习了在 MySQL 客户端中直接执行 SQL 语句来操作数据,但真正在应用开发中,我们是通过编程语言来访问数据库的。比如用C/C++编写的后端服务,需要在自己的代码里连接MySQL、执行SQL、处理结果。那么,如何使用C/C++来访问数据库呢?这就要用到MySQL官方提供的C API库。

在开始编程之前,我们需要做一些准备:

创建一个专门用于连接的 MySQL 用户账号。为了安全和管理,我们不会在代码里直接使用 root 账号。

  • 创建一个测试库 conn。
  • 创建一个账号 xay,并赋予它关于 conn 库的所有权限,且只允许本地登录,执行命令:grant all on conn.* to 'xay'@'localhost';

安装 C/C++ 访问 MYSQL 所需的开发库。例如:在 CentOS 上,可以执行 yum install mysql-devel,这会安装 MYSQL 客户端的头文件和动态链接库。头文件通畅位于 /usr/include/mysql,库文件位于 /user/lib64/mysql。

2.核心API接口与应用

MySQL的C API设计得很直观,整个使用流程就像文件操作一样:打开文件 -> 操作 -> 关闭文件。这里的“文件”就是数据库连接,对应的“句柄”类型是 MYSQL

2.1 初始化和连接

mysql_init()  

函数原型:MYSQL *mysql_init(MYSQL *mysql)

功能:初始化一个MYSQL句柄。在使用任何其他MySQL API之前,必须先调用它来创建和初始化一个连接句柄。

MYSQL *my = mysql_init(nullptr); 这里传nullptr,它会为你分配并返回一个新的MYSQL对象。

mysql_real_connect()

初始化完毕之后,必须用这个函数来建立到数据库服务器的实际连接。

函数原型: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_init的返回值

参数 host:连接的主机的IP/域名

参数 user:登录的用户名

参数 password:登录密码

参数 db:要连接的数据库名

参数 port:MySQL服务端口,通常是3306

参数 unix_socket:域间套接字,本地连接时可指定socket文件路径,否则传nullptr

参数 client_flag:一般设置成0

建立好链接之后,获取英文没有问题,但如果数据库中有中文,查询结果可能会是乱码。这是因为连接的默认字符集是latin1。我们可以在连接成功后,立即设置字符集为 utf8mb4 来解决这个问题。

2.2 执行SQL和获取结果

mysql_query()

函数原型:int mysql_query(MYSQL *mysql, const char *q);

功能:下发并执行一条mysql命令

参数 mysql:mysql_init的返回值

参数 q:要执行的sql语句,如“select * from table”

返回值:如果执行成功,返回0;如果出错,返回非0

获取结果集:区分场景

SQL 执行完后,如果是增、删、改语句,我们主要关心操作是否成功,也就是看mysql_query的返回值和受影响的行数。但如果是查询语句,我们还需要读取返回的数据表,这就要用到结果集相关的函数

如何获取查询结果?如果 mysql_query 执行查询语句并返回成功,我们就通过 mysql_store_result来把结果集从服务器取到客户端内存中。

函数原型:MYSQL_RES *mysql_store_result(MYSQL *mysql);

功能:将服务器返回的整个查询结果集存储到本地。它返回一个 MYSQL_RES 类型的指针,我们可以通过它来解析表格数据

这个函数在内部malloc了一片内存空间来存储查询结果,我们必须在用完结果集后,调用 mysql_free_result(result) 来释放,否则会造成内存泄漏!

解析结果集

拿到 MYSQL_RES * 后,我们就可以像操作一个二维表一样来读取数据了。

获取行数:mysql_num_rows

函数原型:my_ulonglong mysql_num_rows(MYSQL_RES *res)

功能:返回结果集的总行数。

获取列数:mysql_num_fields

函数原型:unsigned int mysql_num_fields(MYSQL_RES *res);

功能:返回结果集的总列数。

获取列名(字段头):mysql_fetch_fields

函数原型:MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);

功能:返回一个包含所有字段信息的数组,数组长度就是列数。我们可以通过 MYSQL_FIELD 结构体中的 name 成员来获取每一列的列名。

MYSQL_FIELD 常用成员属性:

成员名类型说明
namechar *列名(字段名),如 "id""username",这是我们最常用的
tablechar *该列所属的表名(如果查询涉及多表,这个很有用)
dbchar *该列所属的数据库名
catalogchar *目录名,通常总是 "def"
defchar *该列的默认值(如果没有默认值则为NULL)
lengthunsigned long该列定义的最大长度(不是实际数据的长度),比如 varchar(100) 就是 100
typeenum enum_field_types该列的MySQL数据类型,例如 MYSQL_TYPE_LONG(整数)、MYSQL_TYPE_VAR_STRING(变长字符串)等,可以用于判断某列是数字还是字符串
flagsunsigned int列的标志位,一个位掩码,可以组合多种标志,常见的有:
• NOT_NULL_FLAG - 字段不能为空
• PRI_KEY_FLAG - 是主键的一部分
• UNIQUE_KEY_FLAG - 是唯一键的一部分
• AUTO_INCREMENT_FLAG - 是自增字段
• NUM_FLAG - 是数字类型
等等
charsetnrunsigned int该列的字符集编号

获取每一行数据:mysql_fetch_row

函数原型:MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

功能:逐行读取结果集。每次调用,它会返回一个指向当前行数据的 MYSQL_ROW,并把内部指针移到下一行。当没有更多行时,返回NULL。

MYSQL_ROW 本质上是 char **,你可以把它当成一个字符串数组,通过下标 row[0]、row[1]...来访问该行每一列的值。

2.3 接口的使用

上述的部分接口使用方式如下所示:

// 打印表的字段
MYSQL_FIELD *fields_array = mysql_fetch_fields(res);
for(my_ulonglong i = 0; i < fields; i++)
    std::cout << fields_array[i].name << '\t';
std::cout << std::endl;
my_ulonglong rows = mysql_num_rows(res);
my_ulonglong fields = mysql_num_fields(res);
std::cout << "行: " << rows << std::endl;
std::cout << "列: " << fields << std::endl;
for(my_ulonglong i = 0; i < rows; i++)
{
    MYSQL_ROW data = mysql_fetch_row(res);
    for(my_ulonglong j = 0; j < fields; j++)
    {
        std::cout << data[j] << "\t";
    }
    std::cout << std::endl;
}

运行结果:

mysql_real_connect() success
mysql_query success
行: 5
列: 3
id    name    blance
1    张三    100.00
2    李四    200.00
3    王五    300.00
4    赵六    400.00
6    南宫    600.00

上面的例子是单个连接的简单使用。但在真实的Web服务器中,如果每个用户请求都去新建和销毁一个数据库连接,开销会非常大,且无法控制并发连接数。因此,实际应用中通常使用 连接池

连接池 本质上是一个管理数据库连接的容器,内部包含一个线程池和一组预先创建好的MySQL连接对象。当业务线程需要访问数据库时,就从池中“借用”一个空闲连接,用完后再“归还”给池,而不是直接关闭。这样大大提高了性能和资源利用率。

3. 结尾

一个用户逻辑是如何执行的?(以注册和登录为例)

结合我们上面讲到的C/C++访问数据库技术,我们来梳理一下用户注册和登录的后台流程。注意,网站服务器并不是直接裸露地与数据库交互,它们之间通常有一层用编程语言实现的“中间件”或后端服务

注册流程:

  1. 用户向网站A发起注册请求。
  2. 网站A的 Web 服务器收到请求,并返回一个注册页面。
  3. 用户填写用户名、密码等信息并点击提交。
  4. 网站 A 的后端服务(可能由 C/C++/Java/Go 等编写)接收到用户提交的数据,提取出账号、密码等参数。
  5. 后端服务对密码进行加密处理(出于安全考虑,绝不能明文存储)。
  6. 后端服务将注册逻辑构建成一条SQL语句,如 insert into user ...。
  7. 这条SQL被下发给“中间件”(负责负载均衡、分库分表等)。中间件决定将数据写入到哪一个具体的数据库实例。
  8. 在这一步,中间件或最终执行SQL的后台线程,会使用我们上面讲的 mysql_init、mysql_real_connect 等API,从连接池中获取连接,执行insert语句。
  9. 数据库操作成功后,结果一层层返回,最终网站A告诉用户“注册成功”。同时,多个数据库节点间会进行数据同步,保证数据一致性。

登录流程:

  1. 用户向网站A发起登录请求,获得登录页面。
  2. 用户输入账号、密码并提交。
  3. 网站A后端服务接收到请求,提取参数。
  4. 后端服务构建一条查询SQL,如 select user_id, password from user where username='...'。
  5. 通过中间件路由,SQL最终到达具体的数据库。
  6. 在这一步,后台程序再次通过C/C++等语言的API,从连接池获取连接,执行select语句,并通过mysql_store_result和mysql_fetch_row获取查询结果。
  7. 后台程序将查到的加密密码与用户输入密码的加密结果进行比对。
  8. 如果匹配,则为该用户生成一个会话凭证(Session),并返回登录成功;否则,返回账号或密码错误。

通过C/C++的API,我们就打通了应用程序与数据存储之间的桥梁,让死的数据能被灵活地用于活的应用逻辑中。

到此这篇关于MYSQL访问之如何使用C/C++连接数据库的文章就介绍到这了,更多相关mysql使用C/C++连接数据库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Qt实现获取本机IP和定位

    使用Qt实现获取本机IP和定位

    这篇文章主要为大家详细介绍了如何使用Qt实现获取本机IP和定位,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-11-11
  • C++对象排序的比较你了解吗

    C++对象排序的比较你了解吗

    这篇文章主要为大家详细介绍了C++对象排序的比较,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++ I/O文件读写操作的示例代码

    C++ I/O文件读写操作的示例代码

    这篇文章主要介绍了C++ I/O文件读写操作的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • C++的智能指针的原理解析

    C++的智能指针的原理解析

    本文主要介绍了C++中智能指针的使用及其解决内存泄漏问题的方法,传统的指针需要手动释放内存,容易导致内存泄漏,而智能指针可以在生命周期结束时自动释放资源,解决内存泄漏问题,感兴趣的朋友跟随小编一起看看吧
    2026-05-05
  • C语言之直接插入排序算法的方法

    C语言之直接插入排序算法的方法

    这篇文章主要为大家介绍了C语言直接插入排序算法的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • windows消息和消息队列实例详解

    windows消息和消息队列实例详解

    这篇文章主要介绍了windows消息和消息队列实例详解,详细讲述了Windows的消息机制与原理,对于深入理解和学习Windows应用程序设计有不错的借鉴价值,需要的朋友可以参考下
    2014-10-10
  • C++ opencv图像处理实现图像腐蚀和膨胀示例

    C++ opencv图像处理实现图像腐蚀和膨胀示例

    这篇文章主要为大家介绍了C++ opencv图像处理实现图像腐蚀和图像膨胀示例代码,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • getdate()函数的用法实例

    getdate()函数的用法实例

    getdate()函数的用法实例,需要的朋友可以参考一下
    2013-03-03
  • C/C++表格组件Qt TableWidget应用详解

    C/C++表格组件Qt TableWidget应用详解

    本文详细讲解了C/C++中使用列表框组件Qt TableWidget的方法,文中通过示例代码介绍的非常详细。对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • C++超详细分析红黑树

    C++超详细分析红黑树

    这一篇我要跟大家介绍二叉搜索树中的另一颗树——红黑树,它主要是通过控制颜色来控制自身的平衡,但它的平衡没有AVL树的平衡那么严格
    2022-03-03

最新评论