在 MySQL C API 中,MYSQL
、MYSQL_RES
和 MYSQL_FIELD
是三个核心数据结构,分别代表数据库连接、查询结果集和字段元数据。以下是它们的详细解释:
1. MYSQL
- 数据库连接句柄
作用:表示与 MySQL 服务器的连接,是操作数据库的入口点。
关键属性和操作:
c
typedef struct st_mysql {
NET net; // 网络连接信息
char *host; // 服务器主机名
char *user; // 用户名
char *passwd; // 密码
char *db; // 当前数据库
unsigned int port; // 端口号
unsigned long client_flag; // 连接标志
// ... 其他内部状态字段
} MYSQL;
常用操作函数:
c
MYSQL *mysql = mysql_init(NULL); // 初始化连接
mysql_real_connect(mysql, "host", "user", "pass", "db", port, NULL, 0); // 建立连接
mysql_query(mysql, "SELECT * FROM table"); // 执行查询
mysql_close(mysql); // 关闭连接
2. MYSQL_RES
- 查询结果集
作用 :表示 SELECT
、SHOW
等查询返回的结果集。
关键属性和操作:
c
typedef struct st_mysql_res {
uint64_t row_count; // 结果集中的行数
MYSQL_FIELD *fields; // 字段元数据数组
MYSQL_DATA *data; // 结果数据
// ... 其他内部字段
} MYSQL_RES;
常用操作函数:
c
MYSQL_RES *result = mysql_store_result(mysql); // 获取完整结果集
// 或
MYSQL_RES *result = mysql_use_result(mysql); // 获取流式结果集
int num_fields = mysql_num_fields(result); // 获取字段数量
long long num_rows = mysql_num_rows(result); // 获取行数
MYSQL_ROW row = mysql_fetch_row(result); // 获取一行数据
mysql_free_result(result); // 释放结果集
3. MYSQL_FIELD
- 字段元数据
作用:描述结果集中每个字段的结构信息(列定义)。
关键属性:
c
typedef struct st_mysql_field {
char *name; // 字段名
char *org_name; // 原始字段名
char *table; // 所属表名
char *org_table; // 原始表名
char *db; // 所属数据库
char *catalog; // 目录名
char *def; // 默认值
unsigned long length; // 字段长度
unsigned long max_length; // 结果集中的最大长度
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、PRIMARY KEY等)
unsigned int decimals; // 小数位数
unsigned int charsetnr; // 字符集编号
enum enum_field_types type; // 字段类型
} MYSQL_FIELD;
常用操作函数:
c
MYSQL_FIELD *fields = mysql_fetch_fields(result); // 获取所有字段信息
unsigned int num_fields = mysql_num_fields(result);
for (int i = 0; i < num_fields; i++) {
printf("Field %d: %s (Type: %d)\n",
i, fields[i].name, fields[i].type);
}
三者的工作关系
执行查询 包含 包含 MYSQL MYSQL_RES MYSQL_FIELD 数组 MYSQL_ROW 数据
- 连接阶段 :通过
MYSQL
对象建立连接 - 查询阶段:执行 SQL 语句
- 结果处理 :
- 通过
MYSQL_RES
获取结果集 - 通过
MYSQL_FIELD
获取字段结构信息 - 通过
mysql_fetch_row()
获取实际数据行
- 通过
完整使用示例
c
#include <mysql/mysql.h>
#include <stdio.h>
int main() {
MYSQL *conn = mysql_init(NULL);
if (!mysql_real_connect(conn, "localhost", "user", "pass", "db", 0, NULL, 0)) {
fprintf(stderr, "连接失败: %s\n", mysql_error(conn));
return 1;
}
// 执行查询
if (mysql_query(conn, "SELECT id, name, email FROM users")) {
fprintf(stderr, "查询失败: %s\n", mysql_error(conn));
return 1;
}
// 获取结果集
MYSQL_RES *result = mysql_store_result(conn);
if (!result) {
fprintf(stderr, "获取结果集失败: %s\n", mysql_error(conn));
return 1;
}
// 获取字段信息
MYSQL_FIELD *fields = mysql_fetch_fields(result);
int num_fields = mysql_num_fields(result);
// 打印表头
for (int i = 0; i < num_fields; i++) {
printf("%-15s", fields[i].name);
}
printf("\n------------------------------------------------\n");
// 打印数据
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))) {
for (int i = 0; i < num_fields; i++) {
printf("%-15s", row[i] ? row[i] : "NULL");
}
printf("\n");
}
// 清理资源
mysql_free_result(result);
mysql_close(conn);
return 0;
}
字段类型常量(部分)
常量名 | 值 | 对应 SQL 类型 |
---|---|---|
MYSQL_TYPE_TINY |
1 | TINYINT |
MYSQL_TYPE_SHORT |
2 | SMALLINT |
MYSQL_TYPE_LONG |
3 | INT |
MYSQL_TYPE_FLOAT |
4 | FLOAT |
MYSQL_TYPE_DOUBLE |
5 | DOUBLE |
MYSQL_TYPE_STRING |
254 | CHAR/VARCHAR |
MYSQL_TYPE_BLOB |
252 | BLOB/TEXT |
MYSQL_TYPE_TIMESTAMP |
7 | TIMESTAMP |
MYSQL_TYPE_DATE |
10 | DATE |
MYSQL_TYPE_TIME |
11 | TIME |
MYSQL_TYPE_DATETIME |
12 | DATETIME |
重要注意事项
-
资源释放:
- 必须调用
mysql_free_result()
释放结果集 - 必须调用
mysql_close()
关闭连接
- 必须调用
-
结果集生命周期:
c// 错误!result 在 if 块结束后被释放 if (mysql_query(conn, "SELECT ...")) { MYSQL_RES *result = mysql_store_result(conn); } // 此处 result 已失效
-
二进制数据:
- 使用
mysql_real_escape_string()
处理二进制数据 - 对于 BLOB 类型,结果以
char*
形式返回
- 使用
-
空值处理:
cif (row[i] == NULL) { // 处理空值 }
掌握这三个核心结构及其关系是使用 MySQL C API 进行高效数据库开发的基础。