MySQL C API的使用

MySQL C API的使用

介绍及使用

MySQL C API(也称为 MySQL Connector/C)是用于与 MySQL 数据库交互的 C 语言 API。它提供了一组函数和结构体,允许你在 C 程序中连接到 MySQL 数据库服务器,并执行查询、插入、更新等数据库操作。

以下是 MySQL C API 的基本使用步骤:

1. 包含头文件:

在你的 C 代码中包含 MySQL C API 的头文件:

#include <mysql/mysql.h>

2. 初始化和连接:

在程序开始时,需要初始化 MySQL C API 并建立与数据库服务器的连接。以下是一个简单的例子:

c 复制代码
// 这个函数初始化MySQL,并返回一个MYSQL指针。这个指针在后续的操作中都会使用到。
MYSQL *conn;
conn = mysql_init(NULL);

if (conn == NULL) {
    fprintf(stderr, "mysql_init() failed\n");
    exit(1);
}
//连接到数据库:mysql_real_connect()使用这个函数来连接到数据库。其中参数包括上一步得到的MYSQL指针,以及数据库的主机名、用户名、密码、数据库名等。
if (mysql_real_connect(conn, "localhost", "user", "password", "database", 0, NULL, 0) == NULL) {
    fprintf(stderr, "mysql_real_connect() failed\n");
    mysql_close(conn);
    exit(1);
}
// 补充了解
// 最后三个参数大部分情况下为0,NULL,0即可,三个参数详细介绍如下
port:这是数据库服务端的端口号,默认是MySQL的默认端口3306。如果提供0,将使用默认端口;
unix_socket:这是Unix系统专用的,如果mysql服务器运行在本地,并使用了Unix socket,这个参数就指定了该socket的路径。对于运行在网络上的服务器,此参数通常为NULL;
client_flag:这是额外标志,通常为0。对于特殊情况,可以设置为一些特定的值,比如CLIENT_COMPRESS(在客户端和服务器间进行压缩),CLIENT_SSL(使用ssl连接),CLIENT_LOCAL_FILES(允许LOAD DATA LOCAL操作)等等。详情请查阅MySQL的官方文档。
为了兼容更多的使用场景,mysql_real_connect函数给出了很多参数,适合应对各种复杂的数据库连接情况。但是在实际使用中,大部分情况下,使用默认参数(port为0,unix_socket为NULL,client_flag为0)就足够了。

在这个例子中,使用 mysql_init 初始化 MySQL 对象,然后使用 mysql_real_connect 建立与 MySQL 服务器的连接。你需要提供主机名、用户名、密码和数据库名。

3. 执行查询:

一旦连接建立,你可以执行 SQL 查询。以下是一个简单的查询示例:

c 复制代码
//mysql_query()使用这个函数来执行SQL查询。查询结果可以用后续的函数来获取。
if (mysql_query(conn, "SELECT * FROM your_table")) {
    fprintf(stderr, "SELECT query failed: %s\n", mysql_error(conn));
    mysql_close(conn);
    exit(1);
}
//获取查询结果:mysql_store_result() 或 mysql_use_result()这两个函数可以获取查询结果。mysql_store_result()将所有的查询结果存储在客户端,mysql_use_result()则允许你一个接一个地获取结果行。
MYSQL_RES *result = mysql_store_result(conn);		// 注意,返回值是指针
if (result == NULL) {
    fprintf(stderr, "mysql_store_result() failed\n");
    mysql_close(conn);
    exit(1);
}
//遍历结果集:mysql_fetch_row()这个函数可以获取结果集中的一行。你可以在循环中使用它来遍历所有的结果行。
int num_fields = mysql_num_fields(result);
MYSQL_ROW row;		//typedef char **MYSQL_ROW
while ((row = mysql_fetch_row(result))) {
    for (int i = 0; i < num_fields; i++) {
        printf("%s ", row[i] ? row[i] : "NULL");
    }
    printf("\n");
}

mysql_free_result(result);

// 补充了解
typedef struct MYSQL_RES {
  uint64_t row_count;
  MYSQL_FIELD *fields;
  struct MYSQL_DATA *data;
  MYSQL_ROWS *data_cursor;
  unsigned long *lengths; /* column lengths of current row */
  MYSQL *handle;          /* for unbuffered reads */
  const struct MYSQL_METHODS *methods;
  MYSQL_ROW row;         /* If unbuffered read */
  MYSQL_ROW current_row; /* buffer to current row */
  struct MEM_ROOT *field_alloc;
  unsigned int field_count, current_field;
  bool eof; /* Used by mysql_fetch_row */
  /* mysql_stmt_close() had to cancel this result */
  bool unbuffered_fetch_cancelled;
  enum enum_resultset_metadata metadata;
  void *extension;
} MYSQL_RES;

这个例子执行一个简单的 SELECT 查询,然后使用 mysql_store_result 获取查询结果,并使用 mysql_fetch_row 逐行读取结果集中的数据。

4. 插入、更新和删除:

你可以使用 mysql_query 函数执行插入、更新和删除等修改数据库的操作。以下是一个插入数据的示例:

c 复制代码
if (mysql_query(conn, "INSERT INTO your_table (column1, column2) VALUES ('value1', 'value2')")) {
    fprintf(stderr, "INSERT query failed: %s\n", mysql_error(conn));
    mysql_close(conn);
    exit(1);
}

5. 清理结果集:

c 复制代码
//清理结果集:mysql_free_result()当你处理完查询结果后,需要调用这个函数来清理结果集。
mysql_free_result(result);
mysql_close(conn);

6.关闭连接

在程序结束时,确保关闭与 MySQL 服务器的连接并释放资源:

c 复制代码
mysql_close(conn);

这些是 MySQL C API 的基本用法示例。请注意,为了简洁起见,没有进行错误处理的详细检查。在实际应用中,应该更加详细地处理错误以确保程序的稳定性。

API封装

以下为个人在使用过程中,对API的进一步封装

cpp 复制代码
class DataBase {

public:
    ~DataBase() {
        Close();        // 析构函数自动关闭数据库
    }
    // 初始化,可以指定连接的 用户名,密码,数据存储库,host,port
    void Init(string name, string pwd, string database, string host = "localhost", int port = 3306) {
        mysql_init(&mysql_);
       
        // 连接数据库
        if (mysql_real_connect(&mysql_, host.c_str(), name.c_str(), pwd.c_str(), database.c_str(), port, NULL, 0) == NULL) {
            cout << mysql_error(&mysql_) << endl;
            cout << "connect error!" << endl;
            exit(-1);
        }
        // 设置字符集编码,包含了character_set_connection为utf8mb4,因为库以及表采用的是utf8mb4字符集
        if (!mysql_set_character_set(&mysql_, "utf8mb4"))
        {
            printf("New client character set: %s\n", mysql_character_set_name(&mysql_));
        }
        // 设置character_set_client 客户端字符集为GBK,因为命令行窗口是GBK编码,否则mysql 1366 error
        // 设置character_set_results 查询结果集为GBK,因为命令行窗口是GBK编码,要对应起来,否乱码
        if (!Query("set character_set_client = gbk") || !Query("set character_set_results = gbk")) {
            cout << "set character_set_client or character_set_results gbk error:" << Error() << endl;
        }
        
    }
    // 执行语句
    bool Query(const string& query) {
        // 成功0,失败非0
        return !mysql_query(&mysql_, query.c_str());
    }
    // 释放结果集
    void FreeResult() {
        mysql_free_result(res_);
    }
    // 返回记录行数
    int Rows() {
        return mysql_num_rows(res_);
    }
    // 返回字段数量
    int Cols() {
        return mysql_num_fields(res_);
    }
    // 关闭数据库
    void Close() {
        mysql_close(&mysql_);
    }
    // 获取查询结果集
    MYSQL_RES* GetResult() {
        return res_ = mysql_store_result(&mysql_);
    }
    // 获取表字段
    MYSQL_FIELD* GetFields() {
        return mysql_fetch_fields(res_);
    }
    const char* Error() {
        return mysql_error(&mysql_);
    }
    // 获取一行记录
    MYSQL_ROW FetchRow() {
        return row_ = mysql_fetch_row(res_);
    }
    // 不区分大小写进行比较字符串,主要用于字段名比较
    bool InsensistiveStringCompare(const string& str1, const string& str2) {
        string str1Cpy(str1);
        string str2Cpy(str2);
        transform(str1Cpy.begin(), str1Cpy.end(), str1Cpy.begin(), ::tolower);
        transform(str2Cpy.begin(), str2Cpy.end(), str2Cpy.begin(), ::tolower);
        return (str1Cpy == str2Cpy);
    }
    // 输出结果集,便于调试
    void Show(const string& query) {
        if (!Query(query)) {
            cout << "show test error:" << Error() << endl;
            exit(-1);
        }

        MYSQL_RES* res = GetResult();
        if (!res) {
            cout << "GetResult error:" << Error() << endl;
            exit(-1);
        }

        int n = Rows(), m = Cols();
        cout << "共" << n << "条记录," << m << "个字段" << endl;

        MYSQL_ROW row;
        string field;
        vector<vector<string>> records(n + 1, vector<string>(m));
        vector<int> max_len(m);     // 记录每列数据的最大长度,便于格式化输出 
        int len = 0;

        MYSQL_FIELD* fields = GetFields();
        for (int i = 0; i < m; ++i) {
            records[0][i] = fields[i].name;         // 获取字段名
            max_len[i] = (int)max(fields[i].name_length, fields[i].max_length);     // 获取字段记录最大长度以及字段长度,记录最大值
        }

        for (int i = 1; i <= n; ++i) {
            row = FetchRow();
            for (int j = 0; j < m; ++j) {
                if (row[j]) field = row[j];
                else field = "NULL";
                records[i][j] = field;
                len = max(len, sizeof field);
            }
        }

        for (int i = 0; i <= n; ++i) {
            for (int j = 0; j < m; ++j) {
                cout << setiosflags(ios::left) << setw(max_len[j] + 2) << records[i][j] << ' ';
            }
            cout << endl;
        }
    }
private:
    MYSQL mysql_;           // 数据库句柄
    MYSQL_RES* res_;        // 查询结果集合
    MYSQL_ROW row_;         // 记录结构体

};
相关推荐
菲兹园长7 分钟前
表的设计(MYSQL)
数据库·mysql
Java Fans23 分钟前
MySQL数据库常用命令大全(完整版——表格形式)
数据库·mysql
白萝卜弟弟39 分钟前
【MySQL】MySQL函数之JSON_EXTRACT
数据库·mysql·json
gjh120841 分钟前
MySQL常见面试题
数据库·mysql
我的K84091 小时前
Flink整合Hive、Mysql、Hbase、Kafka
hive·mysql·flink
little_kid_pea2 小时前
MySQL Workbench导入数据比mysql命令行慢
数据库·mysql
苹果醋33 小时前
C语言 strlen 函数 - C语言零基础入门教程
java·运维·spring boot·mysql·nginx
爪哇学长3 小时前
解锁数据世界:从基础到精通的数据库探索之旅
数据库·mysql·oracle
码哥字节3 小时前
重生之从零设计 MySQL 架构
数据库·mysql·架构
地图之家家长8 小时前
19.(开发工具篇mysql库)mysql锁表问题解决
数据库·mysql