当前位置: 首页 > news >正文

MySQL常用API

 MySQL常用API

在 C 语言中操作 MySQL 数据库依赖于 MySQL 官方提供的 C API(也称为 libmysqlclient),这套 API 包含一系列函数,覆盖从 “初始化连接” 到 “释放资源” 的全流程。以下按操作顺序分类介绍核心函数,包括函数原型、参数、返回值及使用场景:

一、连接初始化与关闭

这类函数用于初始化 MySQL 连接句柄、建立连接及释放资源,是所有操作的基础。

1. mysql_init
  • 原型
    MYSQL *mysql_init(MYSQL *mysql);
    
  • 功能:初始化 MySQL 连接句柄(MYSQL 结构体),分配内存并设置默认属性。
  • 参数
    • mysql:若为 NULL,函数会自动分配新的 MYSQL 结构体;若传入已存在的句柄,会重置该句柄(清空之前的连接信息)。
  • 返回值
    • 成功:返回初始化后的 MYSQL* 句柄;
    • 失败:返回 NULL(通常因内存不足)。
  • 示例
    MYSQL *conn = mysql_init(NULL);  // 初始化新句柄
    if (conn == NULL) {fprintf(stderr, "初始化失败:内存不足\n");
    }
    
2. mysql_real_connect
  • 原型
    MYSQL *mysql_real_connect(MYSQL *mysql,         // 已初始化的句柄(mysql_init返回值)const char *host,     // MySQL服务器地址(localhost/IP/域名)const char *user,     // 登录用户名(如root)const char *passwd,   // 登录密码const char *db,       // 要连接的数据库名(NULL表示不指定)unsigned int port,    // 端口号(默认3306,传0使用默认)const char *unix_socket,  // Unix套接字(仅Linux/macOS,NULL表示不使用)unsigned long client_flag  // 客户端标志(0表示默认,特殊需求如CLIENT_SSL)
    );
    
  • 功能:与 MySQL 服务器建立实际连接,验证身份并选择数据库。
  • 返回值
    • 成功:返回与参数 mysql 相同的句柄;
    • 失败:返回 NULL(错误信息通过 mysql_error 获取)。
  • 注意
    • 必须先调用 mysql_init 初始化句柄,再调用此函数;
    • 若 db 为 NULL,连接后需用 mysql_select_db 手动切换数据库。
3. mysql_close
  • 原型
    void mysql_close(MYSQL *mysql);
    
  • 功能:关闭与 MySQL 服务器的连接,释放 MYSQL 结构体占用的内存。
  • 注意:所有操作完成后必须调用,否则会导致内存泄漏。

二、SQL 语句执行

这类函数用于向 MySQL 服务器发送 SQL 语句(查询、插入、更新等)并获取执行状态。

1. mysql_query
  • 原型
    int mysql_query(MYSQL *mysql, const char *sql);
    
  • 功能:执行 SQL 语句(字符串需以 \0 结尾,即 C 风格字符串)。
  • 参数
    • mysql:连接句柄;
    • sql:要执行的 SQL 语句(如 SELECT * FROM student)。
  • 返回值
    • 成功:0
    • 失败:非 0(错误信息通过 mysql_error 获取)。
  • 适用场景:执行常规 SQL 语句(无二进制数据,字符串以 \0 结尾)。
2. mysql_real_query
  • 原型
    int mysql_real_query(MYSQL *mysql, const char *sql, unsigned long length);
    
  • 功能:执行 SQL 语句,支持包含二进制数据或 \0 字符的 SQL(需显式指定长度)。
  • 参数
    • lengthsql 字符串的长度(字节数),解决 \0 截断问题。
  • 适用场景:SQL 语句中包含二进制数据(如图片、序列化数据)或 \0 字符时(mysql_query 会因 \0 截断而失败)。

三、查询结果处理

这类函数用于获取 SELECT 语句的查询结果,解析字段和行数据。

1. mysql_store_result
  • 原型
    MYSQL_RES *mysql_store_result(MYSQL *mysql);
    
  • 功能:将查询结果全部加载到客户端内存,适合小结果集(如几十到几千行)。
  • 返回值
    • 成功:返回 MYSQL_RES* 结果集句柄;
    • 失败:返回 NULL(可通过 mysql_field_count 判断是 “无结果” 还是 “错误”)。
  • 优点:可随机访问结果(如反复调用 mysql_fetch_row),支持 mysql_num_rows 获取总行数。
2. mysql_use_result
  • 原型
    MYSQL_RES *mysql_use_result(MYSQL *mysql);
    
  • 功能:初始化一个 “流式结果集”,逐行从服务器获取数据(不加载全部到内存),适合大结果集(如几万行以上)。
  • 返回值:与 mysql_store_result 相同。
  • 注意
    • 必须按顺序读取所有行(不能跳过或回头读),否则会阻塞服务器;
    • 读取期间不能执行其他 SQL 语句(需先读完或调用 mysql_free_result);
    • 不支持 mysql_num_rows(无法提前获取总行数)。
3. mysql_fetch_row
  • 原型
    MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
    
  • 功能:从结果集中获取一行数据(适用于 mysql_store_result 或 mysql_use_result 返回的结果集)。
  • 返回值
    • 成功:返回 MYSQL_ROW 类型(本质是 char**,字符串数组,每个元素对应一个字段值);
    • 失败 / 无更多行:返回 NULL
  • 注意
    • 字段值为 NULL 时,对应数组元素为 NULL(需手动判断);
    • 数据以字符串形式返回(即使字段是数字,需手动转换为 int/float)。
4. mysql_num_fields
  • 原型
    unsigned int mysql_num_fields(MYSQL_RES *result);
    
  • 功能:获取结果集中的字段数(列数)。
5. mysql_fetch_fields
  • 原型
    MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result);
    
  • 功能:获取结果集中所有字段的元信息(如字段名、类型、长度等)。
  • 返回值:返回 MYSQL_FIELD* 数组(长度为 mysql_num_fields 的返回值)。
  • 示例:打印所有字段名
    MYSQL_FIELD *fields = mysql_fetch_fields(result);
    for (int i = 0; i < mysql_num_fields(result); i++) {printf("%s\t", fields[i].name);  // 打印列名
    }
    
6. mysql_free_result
  • 原型
    void mysql_free_result(MYSQL_RES *result);
    
  • 功能:释放结果集占用的内存(必须调用,否则内存泄漏)。

四、事务与状态控制

这类函数用于管理事务、设置字符集、获取连接状态等。

1. mysql_autocommit
  • 原型
    my_bool mysql_autocommit(MYSQL *mysql, my_bool mode);
    
  • 功能:设置事务自动提交模式。
  • 参数
    • mode1 表示自动提交(默认),0 表示手动提交(需显式调用 mysql_commit)。
2. mysql_commit
  • 原型
    my_bool mysql_commit(MYSQL *mysql);
    
  • 功能:提交当前事务(仅当 mysql_autocommit 设为 0 时有效)。
3. mysql_rollback
  • 原型
    my_bool mysql_rollback(MYSQL *mysql);
    
  • 功能:回滚当前事务(取消未提交的操作)。
4. mysql_set_character_set
  • 原型
    int mysql_set_character_set(MYSQL *mysql, const char *csname);
    
  • 功能:设置客户端与服务器通信的字符集(解决中文乱码)。
  • 参数csname 为字符集名称(推荐 utf8mb4,支持所有中文和 emoji)。

五、错误处理

这类函数用于获取操作失败时的错误信息,便于调试。

1. mysql_errno
  • 原型
    unsigned int mysql_errno(MYSQL *mysql);
    
  • 功能:返回最后一次操作的错误代码(0 表示无错误)。
2. mysql_error
  • 原型
    const char *mysql_error(MYSQL *mysql);
    
  • 功能:返回最后一次操作的错误描述字符串(如 Access denied for user)。
  • 示例
    if (mysql_query(conn, sql) != 0) {fprintf(stderr, "错误代码:%u,错误信息:%s\n", mysql_errno(conn), mysql_error(conn));
    }

示例一:

以下是使用 MySQL C API 实现常见数据库操作的代码示例,涵盖连接数据库、查询数据、插入数据、更新数据、删除数据等核心场景,并包含详细注释和错误处理。

前提准备

  • 确保已安装 MySQL 开发库(libmysqlclient),并在编译时链接该库(如 Linux 下用 -lmysqlclient)。
  • 假设存在测试表 student,结构如下:
    CREATE TABLE student (s_id INT PRIMARY KEY AUTO_INCREMENT,  -- 学号(自增)s_name VARCHAR(50) NOT NULL,          -- 姓名s_score INT,                          -- 成绩s_sex CHAR(2)                         -- 性别
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    

示例代码:完整操作集合

#include <stdio.h>
#include <stdlib.h>
#include <mysql.h>  // MySQL C API 头文件// 错误处理宏(简化重复代码)
#define CHECK_ERROR(conn, msg) \if (mysql_errno(conn) != 0) { \fprintf(stderr, "[错误] %s: %s(错误码:%u)\n", msg, mysql_error(conn), mysql_errno(conn)); \mysql_close(conn); \return 1; \}// 1. 连接数据库函数
MYSQL* connect_db(const char* host, const char* user, const char* passwd, const char* db_name, unsigned int port) {MYSQL* conn = mysql_init(NULL);  // 初始化连接句柄if (conn == NULL) {fprintf(stderr, "[错误] 初始化连接句柄失败(内存不足)\n");return NULL;}// 建立连接if (mysql_real_connect(conn, host, user, passwd, db_name, port, NULL, 0) == NULL) {fprintf(stderr, "[错误] 连接数据库失败:%s(错误码:%u)\n", mysql_error(conn), mysql_errno(conn));mysql_close(conn);return NULL;}// 设置字符集(支持中文)if (mysql_set_character_set(conn, "utf8mb4") != 0) {fprintf(stderr, "[错误] 设置字符集失败:%s\n", mysql_error(conn));mysql_close(conn);return NULL;}printf("数据库连接成功!\n");return conn;
}// 2. 查询数据(SELECT)
void query_data(MYSQL* conn) {const char* sql = "SELECT s_id, s_name, s_score, s_sex FROM student WHERE s_score >= 60";if (mysql_query(conn, sql) != 0) {  // 执行查询fprintf(stderr, "[错误] 查询失败:%s\n", mysql_error(conn));return;}// 获取结果集(全部加载到内存)MYSQL_RES* result = mysql_store_result(conn);if (result == NULL) {fprintf(stderr, "[错误] 获取结果集失败:%s\n", mysql_error(conn));return;}// 获取字段数和字段信息int num_fields = mysql_num_fields(result);MYSQL_FIELD* fields = mysql_fetch_fields(result);// 打印表头(字段名)printf("\n===== 查询结果(成绩>=60的学生) =====\n");for (int i = 0; i < num_fields; i++) {printf("%-10s", fields[i].name);  // 左对齐,占10个字符}printf("\n");// 遍历行数据MYSQL_ROW row;while ((row = mysql_fetch_row(result)) != NULL) {for (int i = 0; i < num_fields; i++) {// 字段值可能为NULL,用"NULL"表示printf("%-10s", row[i] ? row[i] : "NULL");}printf("\n");}// 释放结果集mysql_free_result(result);printf("====================================\n");
}// 3. 插入数据(INSERT)
void insert_data(MYSQL* conn) {// 插入语句(使用参数化可防注入,此处简化用字符串拼接)const char* sql = "INSERT INTO student (s_name, s_score, s_sex) VALUES ""('张三', 85, '男'), ""('李四', 92, '男'), ""('王五', 78, '女')";if (mysql_query(conn, sql) != 0) {  // 执行插入fprintf(stderr, "[错误] 插入失败:%s\n", mysql_error(conn));return;}// 获取插入的行数和最后一条记录的自增IDmy_ulonglong affected_rows = mysql_affected_rows(conn);unsigned long long last_id = mysql_insert_id(conn);printf("\n插入成功!影响行数:%llu,最后插入的ID:%llu\n", affected_rows, last_id);
}// 4. 更新数据(UPDATE)
void update_data(MYSQL* conn) {// 将张三的成绩更新为90const char* sql = "UPDATE student SET s_score = 90 WHERE s_name = '张三'";if (mysql_query(conn, sql) != 0) {  // 执行更新fprintf(stderr, "[错误] 更新失败:%s\n", mysql_error(conn));return;}my_ulonglong affected_rows = mysql_affected_rows(conn);printf("\n更新成功!影响行数:%llu\n", affected_rows);
}// 5. 删除数据(DELETE)
void delete_data(MYSQL* conn) {// 删除成绩<60的学生(假设存在)const char* sql = "DELETE FROM student WHERE s_score < 60";if (mysql_query(conn, sql) != 0) {  // 执行删除fprintf(stderr, "[错误] 删除失败:%s\n", mysql_error(conn));return;}my_ulonglong affected_rows = mysql_affected_rows(conn);printf("\n删除成功!影响行数:%llu\n", affected_rows);
}int main() {// 数据库连接参数(替换为你的实际信息)const char* host = "localhost";const char* user = "root";const char* passwd = "your_password";  // 你的MySQL密码const char* db_name = "test_db";       // 数据库名unsigned int port = 3306;// 1. 连接数据库MYSQL* conn = connect_db(host, user, passwd, db_name, port);if (conn == NULL) {return 1;  // 连接失败,退出}// 2. 执行各种操作insert_data(conn);   // 插入数据update_data(conn);   // 更新数据query_data(conn);    // 查询数据delete_data(conn);   // 删除数据(可选)// 3. 关闭连接mysql_close(conn);printf("\n数据库连接已关闭\n");return 0;
}

代码说明

1. 核心函数解析
  • connect_db:封装连接逻辑,包括初始化句柄、建立连接、设置字符集,返回连接句柄(MYSQL*)。
  • query_data:执行 SELECT 语句,获取结果集并打印(包含字段名和行数据),注意处理 NULL 值和释放结果集。
  • insert_data:执行 INSERT 语句,通过 mysql_affected_rows 获取影响行数,mysql_insert_id 获取自增 ID。
  • update_data 和 delete_data:分别执行 UPDATE 和 DELETE,通过 mysql_affected_rows 确认操作效果。
2. 编译与运行
  • Linux/macOS
    gcc mysql_demo.c -o mysql_demo -lmysqlclient  # 编译(链接mysqlclient库)
    ./mysql_demo                                  # 运行
    
3. 关键注意事项
  • 参数化查询:示例中用字符串拼接 SQL 存在 SQL 注入风险,实际开发需用预处理语句(mysql_stmt_init 等),参考:
    // 预处理示例(防注入)
    MYSQL_STMT* stmt = mysql_stmt_init(conn);
    const char* sql = "INSERT INTO student (s_name) VALUES (?)";
    mysql_stmt_prepare(stmt, sql, strlen(sql));
    // 绑定参数...(略)
    
  • 资源释放mysql_free_result(释放结果集)和 mysql_close(关闭连接)必须调用,否则内存泄漏。
  • 错误处理:几乎所有 API 操作都需检查返回值,通过 mysql_error 和 mysql_errno 调试。

通过以上示例,可掌握 C 语言操作 MySQL 的核心流程,根据实际需求扩展功能(如事务处理、批量操作等)

http://www.dtcms.com/a/469483.html

相关文章:

  • DDD企业级记账软件实战二|从0-1创建用户微服务和记账微服务基于Spring Cloud
  • 昆明建设银行纪念币预约网站网站顶一下代码
  • 深入浅出 C# MVC:从基础实践到避坑指南(附完整代码示例)
  • 【网络】NAT相关知识;NAT的概念、工作机制、防火墙(Netfilter)的作用时间点;
  • JavaEE初级——Thread多线程
  • GJOI 10.9 题解
  • 如何设计一个架构良好的前端请求库?
  • 精灵图(雪碧图)的生成和使用
  • Web 开发 27
  • 网站制作主要公司学校网站开发系统的背景
  • Linux小课堂: 目录操作命令深度解析(LS 与 CD 命令)
  • 面向财经新闻的文本挖掘系统设计与实现(论文)
  • 【Redis-cli操作数据类型】Redis八大数据类型详解:从redis-cli操作到场景落地
  • linux安装海量数据库和操作
  • Redis分片+Sentinel熔断设计TP99控制在15ms内
  • 山海关城乡建设局网站佛山网络科技公司有哪些
  • 我的算法模板1(快速幂、逆元、组合数)
  • 八股-2025.10.11
  • 图片上传网站变形的处理旅游网站建设的概念
  • 集团培训网站建设注册公司需要什么条件和手续
  • Spark RDD详解 —— RDD特性、lineage、缓存、checkpoint、依赖关系
  • 玩转Docker系列专栏大纲
  • 网络攻防技术:信息收集技术
  • spark on hive 还是 hive on spark?
  • 搞懂数据通信不用愁!网络基础 + 参考模型 + VRP 配置,一篇全搞定
  • 解决MacOS上CLion调试的时候容器的值显示为0的问题
  • Docker快速入门——第一章Docker入门
  • 建站助手官网淘宝seo具体优化方法
  • 邯郸网站建设哪儿好网站建设参考文献英文书籍
  • STM32 串口收发数据-中断的方式