知识点【MySQL C API】
1、头文件及MYSQL * 句柄
cpp
//头文件
#include <mysql/mysql.h>
1、MYSQL
MYSQL是一个结构体,封装了与数据库连接相关的所有状态,配置和数据。
2、MYSQL *的本质
类似于 FILE*,代表一个与数据库连接的通道,所有对数据库的操作都依赖于这个句柄
每个MYSQL* 句柄都对应一个独立的数据库连接,不能在多线程间共享 (每个线程创建独立的句柄)
3、生命周期
从 init 到 close
4、MYSQL结构体内部管理的内容

大致了解就可以 无需刻意背诵
5、MYSQL *作用
一个程序可以同时连接多个MySQL服务器,每个连接需要独立的MYSQL *句柄区分操作目标。
2、mysql_init()
cpp
**MYSQL *mysql_init(MYSQL *mysql)**
函数功能
初始化一个MYSQL对象,用于后续数据库连接操作
参数
mysql:指向MYSQL结构体的指针。
如果传入NULL ,系统会自动分配并返回一个新对象。
返回值
成功:返回初始化后的MYSQL * 句柄
失败:NULL(如内存不足)
3、mysql_real_connect()
cpp
**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地址,如果是NULL,"localhost","127.0.0.1"被视为与本地主机连接
user:登陆用户名
passwd:登陆密码
db:默认连接的数据库名(可选)
port:服务器端口号(0表示默认端口3306)
unix_socket:套接字或命名管道(通常为NULL)
client_flag:连接标志
返回值
成功:返回传入的MYSQL *句柄
失败:NULL,可通过mysql_error(mysql)获取错误信息。
4、mysql_real_query()
cpp
**int mysql_real_query(MYSQL *mysql,
const char *stmt_str,
unsigned long length)**
函数功能
执行SQL查询(支持二进制数据)
参数
mysql:已连接的 MYSQL 对象
stmt_str:SQL语句字符串(不要以;结尾)
length:语句长度(使用strlen(stmt_str)计算)
返回值
成功:0
失败:返回非0值,需要用mysql_error(mysql)检查错误
5、mysql_store_result()
cpp
**MYSQL_RES *mysql_store_result(MYSQL *mysql)**
函数功能
从服务器获取完整的查询结果集并存储到客户端内存中
参数
mysql:已成功执行查询的MYSQL对象
返回值
成功:MYSQL_RES结果集指针
失败:返回NULL,使用mysql_error(mysql)检错
补充
适用于小型结果集,需要手动调用mysql_free_result()释放内存。
6、mysql_num_fields()
cpp
**unsigned int mysql_num_fields(MYSQL_RES *result)**
函数功能
获取 结果集中的列数
参数
result:mysql_store_result 或者 mysql_use_result 返回的结果集
返回值
列数
7、mysql_num_rows()
cpp
**my_ulonglong mysql_num_rows(MYSQL_RES *result)**
函数功能
获取结果集中的行数(仅对 mysql_store_result 有效)
参数
result:my_result_result 返回的结果集
返回值
行数
补充
如果使用 mysql_use_result 需要遍历所有行才能得到准确行数
8、mysql_fetch_field()
cpp
**MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)**
函数功能
获取结果集中 列的元数据(列名,类型,长度等)
参数
return:结果集指针
返回值
成功:返回MYSQL_FIELD结构体指针
失败:无更多列:NULL
补充
内部会自动指向下一列,无需手动操作
MYSQL_FIELD结构体
cpp
typedef struct st_mysql_field
{
char *name;// 列名(如 "id")
char *org_name;// 原始列名(若使用别名时)
char *table;// 所属表名
char *org_table;// 原始表名(若使用别名时)
char *db;// 所属数据库名
char *catalog;// 目录名(通常为空)
char *def;// 列的默认值
unsigned long length;// 列的定义长度(如 VARCHAR(255) → 255)
unsigned long max_length;// 结果集中实际最大长度(需调用 mysql_store_result 后有效)
unsigned int name_length;
unsigned int org_name_length;
unsigned int table_length;
unsigned int org_table_length;
unsigned int db_length;
unsigned int catalog_length;
unsigned int def_length;
unsigned int flags;// 列的标志(如 NOT_NULL_FLAG)
unsigned int decimals;// 小数位数(如 DECIMAL(10,2) → 2)
unsigned int charsetnr;// 字符集编号
enum enum_field_types type;// 列的数据类型(如 MYSQL_TYPE_INT、MYSQL_TYPE_STRING)
} MYSQL_FIELD;
9、mysql_fetch_row()
cpp
**MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)**
cpp
typedef char **MYSQL_ROW; *// 例如:row[0] 是第一列的值*
函数功能
从结果集中逐行获取数据
参数
result:结果集指针
返回值
成功:返回MYSQL_ROW类型(字符串数组)
失败:无更多行,NULL
补充
内部会自动指向下一行,无需手动操作
10、mysql_free_result()
cpp
**void mysql_free_result(MYSQL_RES *result)**
函数功能
释放 mysql_store_result 分配的 结果集的内存
参数
result:带释放的结果集指针
返回值
无
11、mysql_close()
cpp
**void mysql_close(MYSQL *mysql)**
函数功能
关闭数据库连接,并释放MYSQL对象内存
参数
mysql:已连接的MYSQL
返回值
无
补充
不能重复关闭句柄
可以加上防二次关闭的逻辑
cpp
if(mysql != NULL )
{
mysql_close(mysql);
mysql = NULL;
}
自动清理未释放的结果集:
如果忘记调用mysql_free_result(),mysql_close()会隐式释放结果集,但是显示释放更加直观,更加安全。
综合案例
1、函数补充 mysql_set_character_set
cpp
int mysql_set_character_set(MYSQL *mysql, const char *csname);
函数功能
设置 MySQL 客户端连接(MYSQL*
句柄)的字符集,确保客户端与服务器之间的数据传输使用指定编码。
参数
mysql:已成功连接的MYSQL *句柄
csname:字符集名称字符串
"utf8mb4"
:支持 Unicode 4 字节字符(如 Emoji)。"gbk"
:中文编码。"binary"
:二进制数据。
返回值
成功:0
失败:非0
****以下是不进行编码指定的,向数据库中插入中文(小明)的现象。

2、编译要求
最后需要加上 -lmysqlclient
类似于 我们在线程中添加的-lpthread
l是library(库)的意思
注意
• mysql_store_result()
的作用是获取 上一个查询 的结果集。
代码展示
cpp
#include <mysql/mysql.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
//初始化
MYSQL * conn = mysql_init(NULL);//错误1 这里参数应是NULL
if(conn == NULL)
{
perror("mysql_init");
exit(1);
}
//连接数据库
if(!mysql_real_connect(conn,NULL,"root","","person",3306,NULL,0))
{
fprintf(stderr,"%s\\n",mysql_error(conn));
if(conn != NULL)
{
mysql_close(conn);
conn = NULL;
}
exit(1);
}
mysql_set_character_set(conn, "utf8mb4");
//请求
char *arr_query1 = "select num,name from new_stu";
char *arr_query2 = "insert into new_stu values(109,'小明',18)";
unsigned len_query1 = strlen(arr_query1);
unsigned len_query2 = strlen(arr_query2);
if(mysql_real_query(conn,arr_query1,len_query1))
{
fprintf(stderr,"%s\\n",mysql_error(conn));
if(conn != NULL)
{
mysql_close(conn);
conn = NULL;
}
exit(1);
}
//获取数据集
MYSQL_RES * result = NULL;
if(!(result = mysql_store_result(conn)))
{
fprintf(stderr,"%s\\n",mysql_error(conn));
if(conn != NULL)
{
mysql_close(conn);
conn = NULL;
}
exit(1);
}
//遍历数据库行数 列数
unsigned int len_column = mysql_num_fields(result);
my_ulonglong len_row = mysql_num_rows(result);
printf("column == %u,row == %llu\\n",len_column,len_row);
//遍历数据库的数据
if(len_row != 0)
{
//遍历列的属性
MYSQL_FIELD *filed = NULL;
while(filed = mysql_fetch_field(result))
{
printf("%-10s",filed->name);
}
printf("\\n");
//遍历行数据
MYSQL_ROW row = NULL;
while(row = mysql_fetch_row(result))
{
for (size_t i = 0; i < len_column; i++)
{
printf("%-10s",row[i]);
}
printf("\\n");
}
}
else
{
//无数据
printf("No data on database!\\n");
}
//注意这里 这里我们在这里插入 而不是紧跟着mysql_real_query(conn,arr_query1,len_query1)插入
//让大家更好地理解 结果集的存在 和 mysql_store_result 的逻辑
if(mysql_real_query(conn,arr_query2,len_query2))
{
fprintf(stderr,"%s\\n",mysql_error(conn));
if(conn != NULL)
{
mysql_close(conn);
conn = NULL;
}
exit(1);
}
//关闭数据集
mysql_free_result(result);
//关闭句柄
if(conn != NULL)
{
mysql_close(conn);
conn = NULL;
}
return 0;
}

代码犯错:
1、mysql_init 参数应是NULL,写成 还未初始化的conn
2、没有加字符格式矫正,导致数据库中文乱码
mysql_set_character_set
3、对结果集的理解有误 导致mysql_store_result
以及后续result的使用上 与理想情况出现偏差。复习时重点回想
结束
代码重在练习!
代码重在练习!
代码重在练习!
今天的分享就到此结束了,希望对你有所帮助,如果你喜欢我的分享,请点赞收藏加关注,谢谢大家!!!