16--MySQL使用C语言进行连接

前面讲的都是MySQL命令行的使用,我们后面还要将MySQL与C等其他语言建立连接,才能更好的使用MySQL

前言

要使用 C 语言连接 mysql ,需要使用 mysql 官网提供的库,大家可以去 官网 下载对应的库
MySQL :: MySQL Community Downloads

MySQL开发包

安装

作用

组件类型 示例文件/工具 作用
头文件 mysql.h, errmsg.h 定义API函数、错误码、数据结构(如MYSQL连接句柄)。
库文件 libmysqlclient.so (动态库) 提供连接、查询、事务等功能的实现。
libmysqlclient.a (静态库) 静态链接时使用(较少用,因动态库更灵活)。
配置工具 mysql_config 输出编译选项(如-I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient)。
示例代码 client_test.c(部分包提供) 演示如何使用API进行基本操作(如连接、查询)。

查看我们下载的库和头文件

include 包含所有的方法声明, lib 包含所有的方法实现(打包成库)

与C语言建立MySQL数据库连接的动态库文件是 libmysqlclient.so.20libmysqlclient.so.18(具体取决于MySQL客户端版本)

20对应的是MySQL8.0+版本

18对应的是MySQL5.7以前的版本

补充知识

1.查看MySQL版本
复制代码
mysql --version
2.库的位置

我们上面演示的时候可以看到根目录和/usr目录下都有lib和lib64两个目录,有什么区别吗

特性 /lib(/lib64 ) /usr/lib(/usr/lib64)
用途 系统核心库(启动依赖) 应用程序库(第三方软件)
权限 严格(仅root) 较宽松(root或安装者)
内容示例 libc.so.6, ld-linux.so.2 libmysqlclient.so, libssl.so
是否可删除 ❌ 绝对不可删除(系统崩溃风险) ✅ 可删除(需确认无程序依赖)
FHS标准分类 基础系统(/层级) 应用程序(/usr层级)
3.头文件的位置

include是不会放在根目录下的,因为不是系统启动所必须的,这个目录放在 /usr 目录下

/usr/include

上面的MySQL头文件是在默认路径下,如果在该路径下查找不到,可以使用动态查询

复制代码
mysql_config --include

尝试链接mysql client

通过 mysql_get_client_info() 函数,来验证我们的引入是否成功

这里我们可以看到成功调用了mysql_get_client_info() 函数,说明引入MySQL成功了

至此,MySQL库的引入结束了,接下来是熟悉接口

mysql接口操作

mysql_init()

初始化函数,要使用mysql,就必须要初始化

语法

复制代码
MYSQL* mysql_init(MYSQL *mysql);

--例如
MYSQL* my =mysql_init(NULL);

mysql_real_connect()

链接数据库函数,初始化之后,必须先链接数据库

复制代码
MYSQL *mysql_real_connect(
  MYSQL *mysql,          // 初始化后的连接句柄
  const char *host,      // 服务器主机名/IP
  const char *user,      // 用户名
  const char *passwd,    // 密码
  const char *db,        // 默认数据库名
  unsigned int port,     // 端口号
  const char *unix_socket, // Unix套接字路径
  unsigned long client_flag // 客户端标志位
);

第一个参数 MYSQL 是 C api 中一个非常重要的变量( mysql_init 的返回值),里面内存非常丰富,有 port,dbname,charset等连接基本参数。它也包含了一个叫 st_mysql_methods 的结构体变量,该变量 里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。
mysql_real_connect 函数中各参数,基本都是顾名思意。

解决中文乱码问题

建立好链接之后,获取英文没有问题,如果获取中文是乱码:
设置链接的默认字符集是utf8,原始默认是latin1

复制代码
mysql_set_character_set(myfd, "utf8");

mysql_query()

下发mysql命令函数

复制代码
int mysql_query(MYSQL *mysql, const char *q);

第二个参数是要执行的sql指令,如select * from table

获取数据结果

mysql_store_result()

sql 执行完以后,如果是查询语句,我们当然还要读取数据,如果 update , insert 等语句,那么就看下操 作成功与否即可。我们来看看如何获取查询结果: 如果mysql_query 返回成功,那么我们就通过 mysql_store_result这个函数来读取结果。

复制代码
MYSQL_RES *mysql_store_result(MYSQL *mysql);

该函数会调用 MYSQL 变量中的 st_mysql_methods 中的 read_rows 函数指针来获取查询的结果。同时该 函数会返回MYSQL_RES 这样一个变量,该变量主要用于保存查询的结果。同时该函数 malloc 了一片内存空间来存储查询过来的数据,所以我们一定要记的 free(result), 不然是肯定会造成内存泄漏的。 执行完mysql_store_result 以后,其实数据都已经在 MYSQL_RES 变量中了,所以这个函数实际上就是把结果缓存到内存中

mysql_use_result()

复制代码
MYSQL_RES *mysql_use_result(MYSQL *mysql);

逐行获取结果集,比较节省内存的方法

查询结果集元信息

mysql_num_field()

复制代码
unsigned int mysql_num_fields(MYSQL_RES *result);

返回结果集的列数,用来遍历结果集时确定循环次数

mysql_field_name()

复制代码
const char *mysql_field_name(MYSQL_RES *result, unsigned int field_index);

返回指定列的名称

遍历结果集

mysql_fetch_row()

复制代码
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

返回结果集的下一行数据指针(MYSQL_ROW类型,即字符串数组)

配合mysql_store_result():无更多行时返回NULL

配合mysql_use_result():无更多行或出错时返回NULL(需通过mysql_error()区分)

复制代码
MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
    for (int i = 0; i < mysql_num_fields(res); i++) {
        printf("%s ", row[i] ? row[i] : "NULL"); // 处理NULL值
    }
}

row变量保存mysql_fetch_row返回的数据指针

外层循环 :通过mysql_fetch_row()逐行获取结果集数据,当所有行处理完毕时返回NULL终止循环

内层循环 :遍历当前行的每个字段,mysql_num_fields(res)动态获取结果集的列数

从逻辑上来看,结果集是可以看成一个数组的

  • 行(Row):每一行代表一条数据库记录。
  • 列(Column/Field):每一列代表记录中的一个字段。

错误信息函数

mysql_errno()

获取最近一次MySQL操作产生的错误码(整数)

mysql_error()

获取最近一次MySQL操作的错误描述字符串。

关闭MySQL函数

mysql_close()

复制代码
mysql_close(MYSQL *sock); 

实例

复制代码
#include <stdio.h>
#include <mysql.h>

int main() {


    MYSQL* conn = NULL;     // 数据库句柄
    MYSQL_RES* res = NULL;  // 结果集指针
    MYSQL_ROW row = NULL;   // 行数据指针(修正变量名)

    // 1. 初始化连接句柄
    conn = mysql_init(NULL);
    if (!conn) {
        fprintf(stderr, "初始化失败: %s\n", mysql_error(conn));
        return 1;
    }
    // 2. 解决中文乱码问题
    mysql_set_character_set(conn, "utf8");

    // 3. 建立数据库连接
    const char *host = "localhost";
    const char *user = "shenyu";
    const char *passwd = "Mysql@6666";
    const char *db = "test";
    unsigned int port = 3306;

    if (!mysql_real_connect(conn, host, user, passwd, db, port, NULL, 0)) {
        fprintf(stderr, "连接失败: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 4. 执行SQL查询
    const char *query = "SELECT * FROM stu";
    if (mysql_query(conn, query)) {
        fprintf(stderr, "查询失败: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 5. 获取并处理结果集
    res = mysql_store_result(conn);
    if (!res) {
        fprintf(stderr, "结果集获取失败: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 打印列名
    int num_fields = mysql_num_fields(res);
    int i;  // 将循环变量移到外部
    for (i = 0; i < num_fields; i++) {
        MYSQL_FIELD *field = mysql_fetch_field_direct(res, i);
        printf("%-15s", field->name);
    }
    printf("\n");

    // 遍历行数据
    while ((row = mysql_fetch_row(res))) {
        unsigned long *lengths = mysql_fetch_lengths(res);
        for (i = 0; i < num_fields; i++) {  // 复用外部变量i
            if (row[i]) 
                printf("%-15.*s", (int)lengths[i], row[i]);
            else
                printf("%-15s", "NULL");
        }
        printf("\n");
    }

    // 6. 释放资源
    mysql_free_result(res);
    mysql_close(conn);
    return 0;
}
相关推荐
xmjd msup20 分钟前
mysql的分区表
数据库·mysql
Lyyaoo.20 分钟前
【JAVA Spring面经】Spring 事务失效情况
java·数据库·spring
MeAT ITEM26 分钟前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
dovens30 分钟前
PostgreSQL 中进行数据导入和导出
大数据·数据库·postgresql
IOT.FIVE.NO.130 分钟前
claude code desktop cowork报错解决和记录Workspace..The isolated Linux environment ...
linux·服务器·数据库
Rick199338 分钟前
mysql 慢查询怎么快速定位
android·数据库·mysql
科技小花8 小时前
全球化深水区,数据治理成为企业出海 “核心竞争力”
大数据·数据库·人工智能·数据治理·数据中台·全球化
X56619 小时前
如何在 Laravel 中正确保存嵌套动态表单数据(主服务与子服务)
jvm·数据库·python
虹科网络安全10 小时前
艾体宝干货|数据复制详解:类型、原理与适用场景
java·开发语言·数据库
2301_7717172110 小时前
解决mysql报错:1406, Data too long for column
android·数据库·mysql