• 【MySQL系列】使用C语言连接MySQL


    「前言」文章内容大致是使用C语言连接MySQL

    「归属专栏」MySQL

    「主页链接」个人主页

    「笔者」枫叶先生(fy)

    MySQL

    一、Connector/C使用

    按照前面MySQL的安装流程,安装完MySQL,MySQL相应的连接相关的库也被下载下来了
    查看动态库是否存在

    ls /lib64/mysql/
    
    • 1

    在这里插入图片描述
    查看MySQL相应的头文件是否存在

    ls /usr/include/mysql
    
    • 1

    在这里插入图片描述
    如果不存在,需要安装一下

     yum install -y mysql-devel
    
    • 1

    在这里插入图片描述
    下面先通过调用mysql_get_client_info来判断库是否引入成功,该函数的作用就是获取客户端的版本信息

    #include 
    #include 
    
    int main()
    {
        std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    进行编译

    g++ -o mysql mysql.cpp -L/lib64/mysql -lmysqlclient
    
    • 1
    • -L:用于指定库文件的搜索路径
    • -l:用于指明需要连接库文件路径下的哪一个库(L的小写)

    这些在动静态库那里都讲过了,不再解释

    运行可执行程序后,可以看到客户端的版本号
    在这里插入图片描述

    至此库已经成功被引入,接下来就是库函数的使用了

    二、MySQL的C接口介绍

    2.1 连接MySQL

    1、初始化

    在连接数据库之前,需要先创建一个MySQL对象,进行初始化

    该函数如下:

    MYSQL* mysql_init(MYSQL *mysql);
    
    • 1

    说明:

    • 该函数用来分配或者初始化一个MySQL对象
    • 如果传入参数为NULL,mysql_init将自动分配一个MYSQL对象(句柄)并返回
    • 如果传入的是一个MYSQL对象,该函数会对该对象进行初始化

    MYSQL是一个结构体,定义如下:
    在这里插入图片描述
    在这里插入图片描述

    2、连接数据库

    初始化完毕之后,必须先链接数据库,才能进行后续操作(mysql网络部分是基于TCP/IP的)

    连接数据库的函数如下:

    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 clientflag);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    参数说明:

    • mysql:表示在连接数据库前,调用mysql_init函数创建的MYSQL对象
    • host:表示需要连接的MySQL服务器的IP地址,"127.0.0.1"表示连接本地MySQL服务器
    • user:表示连接MySQL服务器时,登录所使用的用户名
    • passwd:表示连接MySQL服务器时,登录所使用用户的密码
    • db:表示连接MySQL服务器后,需要使用的是哪一个数据库
    • port:表示连接的MySQL服务器,所对应的端口号
    • unix_socket:表示连接时应该使用的套接字或命名管道,通常设置为NULL
    • clientflag:可以设置为多个标志位的组合,表示允许特定的功能,通常设置为0

    返回值

    • 如果连接数据库成功,则返回一个MYSQL对象(句柄),该对象与第一个参数mysql相同
    • 如果连接数据库失败,则返回NULL

    3、关闭数据库连接

    与数据库交互完毕后,需要关闭数据库连接

    关闭数据库连接的函数如下:

    void mysql_close(MYSQL *sock);
    
    • 1

    说明:

    • 参数sock,就是连接数据库前调用mysql_init创建的MySQL对象,传入该对象即可

    连接测试

    代码如下:

    #include 
    #include 
    #include 
    using namespace std;
    
    const string host = "127.0.0.1";
    const string user = "fengye";
    const string password = "123123aa";
    const string db = "test_db";
    const int port = 3306;
    
    int main()
    {
        // 1.初始化
        MYSQL* my = mysql_init(nullptr);
        // 2.连接数据库
        if(mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
        {
            cerr << "数据库连接失败!" << endl;
            return 1;
        }
        cout << "连接成功" << endl;
        // 3.关闭连接
        mysql_close(my);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    进行编译运行,数据库连接成功
    在这里插入图片描述

    2.2 发送SQL请求

    数据库连接成功了,就可以进行进行发送SQL请求了

    设置编码格式

    在连接数据库之后,需要统一客户端和服务器的编码格式,避免在数据交互过程中出现乱码,设置编码格式的函数如下:

    int mysql_set_character_set(MYSQL *mysql, const char *csname);
    
    • 1

    说明:

    • 参数mysql:是mysql_init函数创建初始化的MYSQL对象
    • csname:表示要设置的编码格式,如"utf8"

    返回值:为0表示设置成功,否则表示设置失败

    注:设置链接原始默认字符集是latin1

    发送SQL请求

    下发SQL请求的函数如下:

    int	mysql_query(MYSQL *mysql, const char *q);
    
    • 1

    说明:

    • mysql:是mysql_init函数创建初始化的MYSQL对象
    • q: 表示向MySQL服务器下发的SQL请求,SQL最后可以不带分号,也可以带

    返回值:为0表示SQL执行成功,否则表示SQL执行失败

    向数据库中插入数据

    #include 
    #include 
    #include 
    using namespace std;
    
    const string host = "127.0.0.1";
    const string user = "fengye";
    const string password = "123123aa";
    const string db = "test_db";
    const int port = 3306;
    
    int main()
    {
        // 1.初始化
        MYSQL* my = mysql_init(nullptr);
        // 2.连接数据库
        if(mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
        {
            cerr << "数据库连接失败!" << endl;
            return 1;
        }
        cout << "连接成功" << endl;
    
        // 设置编码格式
        mysql_set_character_set(my, "utf8");
    
        string sql = "insert into user (name, age) values ('王五', 19);";
        if(mysql_query(my, sql.c_str()) != 0)
        {
            cerr << sql << " failed." << endl;
            return 2;
        }
        cout << sql << " sucsess." << endl;
        // 3.关闭连接
        mysql_close(my);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    编译运行
    在这里插入图片描述

    删除数据库中的数据

    进行删除数据测试
    在这里插入图片描述
    编译运行
    在这里插入图片描述

    修改数据库中的数据

    进行修改数据库数据测试
    在这里插入图片描述
    编译运行
    在这里插入图片描述

    2.3 获取结果集

    • 对数据库中的数据进行增删改操作时,都只需要调用mysql_query向服务器下发对应的SQL请求,即不需要返回结果
    • 对于数据库中的数据进行查询操作时,除了需要调用mysql_query向服务器下发对应的查询SQL,还需要获取查询结果,把MySQL服务器查到的数据获取过来

    获取查询结果的函数如下:

    MYSQL_RES* mysql_store_result(MYSQL *mysql);
    
    • 1

    注:

    • 获取到的查询结果保存到MYSQL_RES变量中
    • 该函数malloc了一片内存空间来存储查询过来的数据,需要进行释放该空间,否则会造成内存泄漏

    MYSQL_RES是一个结构体,定义如下:
    在这里插入图片描述
    释放结果集函数:

    void mysql_free_result(MYSQL_RES *result);
    
    • 1

    说明:参数传入结果集即可

    获取结果集成功后,需要获取结果集的行数和列数,方便进行遍历数据

    获取查询结果的行数

    获取查询结果的行数的函数如下:

    my_ulonglong mysql_num_rows(MYSQL_RES *res);
    
    • 1

    获取查询结果的列数

    获取查询结果的列数的函数如下:

    unsigned int mysql_num_fields(MYSQL_RES *res);
    
    • 1

    获取查询结果中的一行数据

    MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
    
    • 1

    注:

    • 该函数将会从指定的MYSQL_RES对象中,获取查询结果中的一行数据

    获取列名

    获取查询结果的列属性的函数如下:

    MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES *res);
    
    • 1

    注:

    • 列属性也是需要进行特定获取的
    • 每个MYSQL_FIELD对象中保存着对应列的各种列属性
    • 我们需要获取列名称,即name

    MYSQL_FIELD结构体定义如下:
    在这里插入图片描述

    遍历结果集类似于遍历二维数组

    查询演示

    #include 
    #include 
    #include 
    using namespace std;
    
    const string host = "127.0.0.1";
    const string user = "fengye";
    const string password = "123123aa";
    const string db = "test_db";
    const int port = 3306;
    
    int main()
    {
        // 1.初始化
        MYSQL* my = mysql_init(nullptr);
        // 2.连接数据库
        if(mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
        {
            cerr << "数据库连接失败!" << endl;
            return 1;
        }
        cout << "连接成功" << endl;
    
        // 设置编码格式
        mysql_set_character_set(my, "utf8");
    
        // string sql = "insert into user (name, age) values ('王五', 19);";
        // string sql = "delete from user where id=4";
        // string sql = "update user set age=66 where id=1";
        string sql = "select * from user";
        if(mysql_query(my, sql.c_str()) != 0)
        {
            cerr << sql << " failed." << endl;
            return 2;
        }
        cout << sql << " sucsess." << endl;
    
        // 获取结果集
        MYSQL_RES* res = mysql_store_result(my);
        int row = mysql_num_rows(res);   // 数据行数
        int col = mysql_num_fields(res); // 数据列数
        
        // 获取每列的属性,并打印
        MYSQL_FIELD* fields = mysql_fetch_field(res);
        for(int i = 0; i < col; ++i)
        {
            cout << fields[i].name << "\t";
        }
        cout << endl;
    
        // 遍历数据
        for(int i = 0; i < row; ++i)
        {
            // 获取每一行
            MYSQL_ROW rows = mysql_fetch_row(res);
            for(int j = 0; j < col; ++j)
            {
                cout << rows[j] << "\t";
            }
            cout << endl;
        }
    
        // 释放res
        mysql_free_result(res);
    
        // 3.关闭连接
        mysql_close(my);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    编译运行,数据成功被获取出来
    在这里插入图片描述

    • 再说一下结果集,结果集指向一个数组,数组里面存放的都是char**的指针
    • 使用mysql_fetch_row函数获取一行,返回的结果实际是char**,char**又指向一个char*的数组
      在这里插入图片描述
      --------------------- END ----------------------
    「 作者 」 枫叶先生
    「 更新 」 2023.9.14
    「 声明 」 余之才疏学浅,故所撰文疏漏难免,
              或有谬误或不准确之处,敬请读者批评指正。
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    Linux JumpServer 堡垒机远程访问
    三相Vienna整流器电流畸变的抑制方法
    bash: ./a.sh: /bin/bash^M: bad interpreter: No such file or directory的解决方法
    1-2 暴力破解-模拟
    k8s暴露集群内和集群外服务的方法
    C++进制转换题
    Python字典-Dict使用
    OpenCV使用教程-图像边界填充
    单行、多行文本超出显示省略号
    代码随想录刷题Day55 | 392. 判断子序列 | 115. 不同的子序列
  • 原文地址:https://blog.csdn.net/m0_64280701/article/details/132788701