C语言怎么连接到MySQL数据库并实现增删改查

来源:Python编程网作者:高宇头衔:草根站长
导读:本期聚焦于小伙伴创作的《C语言怎么连接到MySQL数据库并实现增删改查》,敬请观看详情。想在嵌入式设备或后端服务里用C语言直接操作MySQL,第一步就是搭好编译环境和连接句柄。MySQL官方提供了C语言客户端库,也就是MySQL C API,通过mysql_real_connect函数就能建立TCP连接。不少新手卡在头文件找不到或链接时报错,其实只要装好libmysqlclient开发包并在编译时加上对应参数即可。连接成功后,执行SQL靠mysql_query发送语句,再用mysql_store_result取回结果集,逐行读取字段。本文以具体代码演示建连、插入、查询与关闭的完整流程,并说明字符集与错误排查的注意点,帮你少走弯路。

在C语言项目中访问MySQL,最常用也最稳定的方式是通过官方提供的MySQL C API。这套接口以动态库形式发布,头文件为mysql.h,核心结构体是MYSQL连接句柄。借助它,我们可以完成网络连接、认证、执行SQL以及处理结果集等全部操作。下面先给出基础环境准备与连接示例。

C语言怎么连接到MySQL数据库并实现增删改查

一、环境准备与编译配置

在Linux系统下,需要安装MySQL客户端开发包,通常包名是libmysqlclient-dev或者mariadb-connector-c-dev。安装后,系统中会出现/usr/include/mysql/mysql.h以及对应的动态库文件。如果没有这个开发包,编译阶段就会报找不到头文件的错误。

编译时除了包含头文件目录,还必须链接mysqlclient库。例如使用gcc编译时可以写:gcc main.c -o app $(mysql_config --cflags) $(mysql_config --libs)。mysql_config工具能自动输出正确的include和lib参数,避免手动写错路径。Windows下则需要在Visual Studio里配置包含目录和库目录,并额外链接libmysql.lib。

二、建立数据库连接

连接MySQL前,先调用mysql_init初始化一个MYSQL结构体指针,再使用mysql_real_connect填入主机、用户、密码、库名和端口。这个函数返回同样的指针表示成功,返回NULL则表示失败,此时要用mysql_error查看具体原因。下面是一段最小可运行的连接代码。

#include <mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn = mysql_init(NULL);
    if (conn == NULL) {
        printf("mysql_init失败n");
        return 1;
    }
    // 连接本地MySQL,用户root,密码123456,库名test,端口3306
    if (mysql_real_connect(conn, "127.0.0.1", "root", "123456", "test", 3306, NULL, 0) == NULL) {
        printf("连接错误: %sn", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }
    printf("连接成功n");
    mysql_close(conn);
    return 0;
}

上面的代码演示了最基础的连接与断开。需要注意,mysql_real_connect的第七个参数是unix socket路径,在跨网络访问时传NULL即可;第八个参数是客户端标志,一般填0。如果连接的是远程服务器,要确保MySQL服务端开启了远程账号权限,并且防火墙放行了3306端口。

另外,建议在连接后立刻执行mysql_set_character_set(conn, "utf8mb4"),避免后续插入中文出现乱码。MySQL 8.0默认认证插件改为caching_sha2_password,老版本的C客户端库可能连不上,此时要么升级客户端库,要么将账号改回mysql_native_password。

三、执行增删改查操作

对于INSERT、UPDATE、DELETE这类不返回结果集的语句,直接调用mysql_query发送即可,返回0代表执行成功。如果影响行数为0,并不代表出错,只是没有匹配到记录。通过mysql_affected_rows可以拿到受影响行数。

#include <mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn = mysql_init(NULL);
    mysql_real_connect(conn, "127.0.0.1", "root", "123456", "test", 3306, NULL, 0);
    mysql_set_character_set(conn, "utf8mb4");

    const char *sql = "INSERT INTO user(name, age) VALUES('张三', 20)";
    if (mysql_query(conn, sql) != 0) {
        printf("插入失败: %sn", mysql_error(conn));
    } else {
        printf("插入成功,影响行数: %lldn", mysql_affected_rows(conn));
    }
    mysql_close(conn);
    return 0;
}

查询操作稍微复杂一些。执行SELECT后必须调用mysql_store_result把结果集拉到本地内存,然后用mysql_fetch_row逐行获取,mysql_num_fields拿到列数。处理完结果要调用mysql_free_result释放内存,否则会造成泄漏。

#include <mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn = mysql_init(NULL);
    mysql_real_connect(conn, "127.0.0.1", "root", "123456", "test", 3306, NULL, 0);

    mysql_query(conn, "SELECT id, name FROM user");
    MYSQL_RES *res = mysql_store_result(conn);
    if (res == NULL) {
        printf("查询出错: %sn", mysql_error(conn));
        return 1;
    }
    MYSQL_ROW row;
    while ((row = mysql_fetch_row(res)) != NULL) {
        printf("id=%s, name=%sn", row[0], row[1]);
    }
    mysql_free_result(res);
    mysql_close(conn);
    return 0;
}

对于包含用户输入的SQL,绝对不能用字符串拼接的方式,否则会产生注入风险。正确做法是使用mysql_stmt_init配合mysql_stmt_prepare和mysql_stmt_bind_param实现预处理语句,既能防注入也能提升重复执行效率。删除和更新语句的写法与插入类似,只是SQL文本不同,同样通过mysql_affected_rows确认效果。

四、错误处理与资源释放

任何MySQL C API调用失败都要通过mysql_error(conn)获取人类可读的错误描述,mysql_errno(conn)则返回数字错误码,方便日志分类。长连接程序中,如果网络抖动导致连接断开,mysql_ping可以检测并重连。

所有打开的资源——连接句柄、结果集、预处理语句——都必须成对释放。忘记mysql_free_result或mysql_stmt_close会在长时间运行的服务里累积内存占用。写工具函数时建议统一封装连接、执行和关闭逻辑,业务代码只关心SQL与绑定参数,这样既安全又易维护。

操作类型核心函数是否需要释放结果
连接mysql_real_connect否,但需mysql_close
写操作mysql_query
读操作mysql_store_result是,mysql_free_result
预处理mysql_stmt_prepare是,mysql_stmt_close

掌握了上述连接、执行与释放的基本模式,C语言操作MySQL就不再神秘。实际工程中建议进一步封装连接池、日志与重试机制,让数据库层更健壮。

C语言MySQL连接MySQL_C_API修改时间:2026-08-01 20:54:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。