一、前提准备
-
已在Linux系统中安装MySQL服务;
-
已创建好数据库、表和对应的用户账号;
-
已安装MySQL开发库头文件和lib库(如:
sudo apt install libmysqlclient-dev); -
使用的数据库信息如下:
#define KING_DB_SERVER_IP "10.0.0.129"
#define KING_DB_SERVER_PORT 3306
#define KING_DB_USERNAME "admin"
#define KING_DB_PASSWORD "123456"
#define KING_DB_DEFAULTDB "KING_DB"
二、完整代码(插入 + 查询)
#include <mysql.h> // MySQL 客户端 API 头文件
#include <string.h> // 字符串处理函数
#include <stdio.h> // 标准输入输出
// 数据库连接信息宏定义
#define KING_DB_SERVER_IP "10.0.0.129" // MySQL 服务器地址
#define KING_DB_SERVER_PORT 3306 // MySQL 服务器端口
#define KING_DB_USERNAME "admin" // 登录用户名
#define KING_DB_PASSWORD "123456" // 登录密码
#define KING_DB_DEFAULTDB "KING_DB" // 默认数据库名
// SQL语句:插入数据和查询数据
#define SQL_INSERT_TBL_USER "INSERT TBL_USER(U_NAME,U_GENGDER) VALUES('charon','man');"
#define SQL_SELECT_TBL_USER "SELECT * FROM TBL_USER;"
// 查询函数,执行 SELECT 语句并输出结果
int king_mysql_select(MYSQL *mysql) {
// 执行查询语句
if (mysql_real_query(mysql, SQL_SELECT_TBL_USER, strlen(SQL_SELECT_TBL_USER))) {
printf("mysql_real_query : %s\n", mysql_error(mysql)); // 查询失败时输出错误信息
return -1;
}
// 从服务器获取结果集
MYSQL_RES *res = mysql_store_result(mysql);
if (res == NULL) {
printf("mysql_store_result : %s\n", mysql_error(mysql)); // 失败时输出错误信息
return -2;
}
// 获取返回的行数和列数
int rows = mysql_num_rows(res);
printf("rows: %d\n", rows); // 输出总行数
int fields = mysql_num_fields(res);
printf("fields: %d\n", fields); // 输出总列数
// 遍历结果集
MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
for (int i = 0; i < fields; i++) {
// row[i] 可能为 NULL,要做空指针判断
printf("%s\t", row[i] ? row[i] : "NULL");
}
printf("\n");
}
// 释放结果集内存
mysql_free_result(res);
return 0;
}
// 主函数入口
int main() {
MYSQL mysql;
// 初始化 MYSQL 结构体
if (NULL == mysql_init(&mysql)) {
printf("mysql_init : %s\n", mysql_error(&mysql));
return -1;
}
// 连接到数据库服务器(返回 NULL 表示连接失败)
if (!mysql_real_connect(&mysql,
KING_DB_SERVER_IP,
KING_DB_USERNAME,
KING_DB_PASSWORD,
KING_DB_DEFAULTDB,
KING_DB_SERVER_PORT,
NULL,
0)) {
printf("mysql_real_connect : %s\n", mysql_error(&mysql));
return -2;
}
// 执行插入语句(将用户数据写入数据库)
if (mysql_real_query(&mysql, SQL_INSERT_TBL_USER, strlen(SQL_INSERT_TBL_USER))) {
printf("mysql_real_query : %s\n", mysql_error(&mysql));
return -3;
}
// 执行查询操作
king_mysql_select(&mysql);
// 关闭数据库连接
mysql_close(&mysql);
return 0;
}
三、重点函数解析(查询相关)
1. mysql_real_query()
if (mysql_real_query(mysql, SQL_SELECT_TBL_USER, strlen(SQL_SELECT_TBL_USER)))
-
用于执行 SQL 语句(不仅限于 SELECT,还可执行 INSERT、UPDATE、DELETE 等)。
-
参数说明:
-
mysql:数据库连接对象指针; -
SQL_SELECT_TBL_USER:SQL 查询语句; -
strlen(...):语句长度;
-
-
注意:返回 0 表示成功,非 0 表示失败,要配合
mysql_error()获取错误信息。
2.mysql_store_result()
MYSQL_RES *res = mysql_store_result(mysql);
-
用于从服务器获取查询结果集,返回值为
MYSQL_RES*; -
如果查询语句无结果返回,或者发生错误,返回 NULL;
-
这是查询后必须调用的函数,否则将无法访问返回的多行数据。
3.mysql_num_rows() & mysql_num_fields()
int rows = mysql_num_rows(res);
int fields = mysql_num_fields(res);
-
mysql_num_rows(res):返回结果集中总共有多少行(记录); -
mysql_num_fields(res):返回结果集中有多少列(字段);
4.mysql_fetch_row()
while ((row = mysql_fetch_row(res))) {
for (int i = 0; i < fields; i++) {
printf("%s\t", row[i] ? row[i] : "NULL");
}
printf("\n");
}
-
逐行获取查询结果;
-
返回的是一个
MYSQL_ROW类型,它本质上是一个char*数组(即每列字段的值); -
需要遍历
fields次来打印每一行的所有字段; -
某些字段可能为
NULL,建议加空指针判断,防止打印异常或程序崩溃。
四、交互原理简析
MySQL查询的交互过程可以简单理解为:
客户端程序(C语言)
↓ 使用 API 构造 SQL 查询语句(如 SELECT * FROM TBL_USER;)
MySQL 客户端通过 TCP(默认端口 3306)连接服务器
↓ 使用 mysql_real_connect() 建立连接
发送查询语句到服务器执行
↓ 使用 mysql_real_query() 执行 SQL
MySQL 服务器解析 SQL、执行查询,生成结果集
↓ 服务器通过网络返回结果集数据
客户端接收结果集
↓ 使用 mysql_store_result() 获取结果集指针
程序处理结果集
↓ 使用 mysql_fetch_row() 遍历每一行
↓ 显示/打印每列字段内容
释放结果集
↓ 使用 mysql_free_result() 释放内存
关闭连接
↓ 使用 mysql_close() 断开与数据库连接
-
结果集并不是自动返回的,需要客户端主动去调用
mysql_store_result()来接收; -
每一行的数据通过
mysql_fetch_row()获取,是一个字段数组; -
最后一定要记得释放资源并断开连接。
五、调试中遇到的常见问题
在写这段代码时,我遇到一个经典错误:
// 错误写法
mysql_real_query(&mysql,SQL_SELECT_TBL_USER,strlen(SQL_SELECT_TBL_USER)); // 参数是 MYSQL **,错误!
// 正确写法
mysql_real_query(mysql,SQL_SELECT_TBL_USER,strlen(SQL_SELECT_TBL_USER)); // 参数是 MYSQL *,OK
-
mysql_real_query()和mysql_store_result()的参数类型是MYSQL *,不是MYSQL ** -
我错误地在函数调用中又取了地址,导致类型不匹配,编译可能通过但运行会崩溃或行为异常
-
正确做法是函数参数写为
MYSQL *mysql,调用时传入变量mysql即可,不加&
766

被折叠的 条评论
为什么被折叠?



