• C语言访问Mysql


    C语言访问Mysql

    1. 环境设置

    环境设置这里我就简单介绍一下,参考我mysql环境安装的博客:MySQL环境安装_Ryujianli的博客-CSDN博客

    如果你像我一样在linux下安装了mysql,就能在对应的目录下找到库和头文件

    ls /lib64/mysql
    ls /usr/include/mysql
    
    • 1
    • 2

    在这里插入图片描述

    如果你找不到,可以再安装一下

    yum install mysql-devel
    
    • 1

    配置好环境后,直接打开vscode开始测试,要#include引入mysql的头文件

    注意makefile文件的写法:

    mytest:test.cc
    	g++ -o mytest test.cc -L/lib64/mysql -lmysqlclient -std=c++11 
    .PHONY:clean
    clean:
    	rm -f mytest
    
    • 1
    • 2
    • 3
    • 4
    • 5

    测试代码:

    #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

    如果上面代码能成功运行证明你的库引入成功

    在这里插入图片描述

    2. mysql接口介绍

    (1) 初始化mysql_init()

    要使用库,必须先进行初始化!

    MYSQL * mysql_init(MYSQL *mysql)
    
    参数说明:  mysql设置为nullptr, 函数分配,初始化,并返回一个新的对象。
    返回值:    成功返回一个MYSQL类型的对象, 失败返回nullptr
    
    • 1
    • 2
    • 3
    • 4

    (2) 链接数据库mysql_real_connect

    初始化完毕之后,必须先链接数据库,在进行后续操作。(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);
    参数说明:
    		mysql: 你创建并初始化好的MYSQL类型的对象, 即mysql_init的返回值
    		host: 这里使用本地环回地址,"127.0.0.1"
    		user: 代表数据库的使用者
            passwd: userd的密码
    		db: 代表你要连接的数据库名称
            port: mysql服务的端口号, 默认是3306
            unix_socket: unix套接字, 设置为nullptr代表这里是网络通信   
    		clientflag: 设置为0
    返回值:
             成功返回连接成功的MYSQL对象, 失败返回nullptr
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    第一个参数 MYSQL是 C api中一个非常重要的变量(mysql_init的返回值),里面内存非常丰富有port, dbname, charset等连接基本参数。它也包含了一个叫 st_mysql_methods的结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。mysql_real_connect函数中各参数,基本都是顾名思意。

    建立好链接之后,获取英文没有问题,如果获取中文是乱码:设置链接的默认字符集是utf8,原始默认是latin1

    mysql_set_character_set(myfd, "utf8");
    
    • 1

    (3) 下发mysql命令mysql_query()

    int mysql_query(MYSQL *mysql, const char *q);
    
    参数说明: 
    		第一个参数上面已经介绍过
     		q: 代表你要执行的sql语句
    返回值:
    		成功返回0, 失败返回非0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (4) 获取执行结果mysql_store_result

    sql执行完以后,如果是查询语句,我们当然还要读取数据,如果update,insert等语句,那么就看下操作成功与否即可。我们来看看如何获取查询结果: 如果mysql_query返回成功,那么我们就通过mysql_store_result这个函数来读取结果。原型如下:

    MYSQL_RES *mysql_store_result(MYSQL *mysql);
    
    • 1

    MYSQL_RES的介绍:

    • 该函数会调用MYSQL变量中的st_mysql_methods中的 read_rows 函数指针来获取查询的结果

    • 。同时该函数会返回MYSQL_RES 这样一个变量,该变量主要用于保存查询的结果(调用mysql_store_result函数时是把存储的数据转储到MYSQL_RES中)。

    • 同时该函数malloc了一片内存空间来存储查询过来的数据,所以一定要使用mysql_free_result() 函数来释放,否则会造成内存泄漏。

    • 执行完mysql_store_result以后,其实数据都已经在MYSQL_RES变量中了。

    在这里插入图片描述

    MYSQL_RES叫做结果集,我们可以把想象成一个char**类型的,每一小块空间里存储的是一条记录中的某一个数据所以要用一个char *类型的指针去指向这一个数据,一行的数据就构成一条记录,一共有多少条记录就有多少行,每一行都会有一个二维指针去指向这一行

    (5) 释放结果集mysql_free_result()

    void mysql_free_result(MYSQL_RES *result)
    
    • 1

    (6) 获取结果行数mysql_num_rows

    my_ulonglong mysql_num_rows(MYSQL_RES *res);
    
    • 1

    在这里插入图片描述

    (7) 获取结果列数mysql_num_fields

    unsigned int mysql_num_fields(MYSQL_RES *res);
    
    • 1

    (8) 获取列名mysql_fetch_fields

    MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);
    
    • 1

    (9) 获取结果内容mysql_fetch_row

    MYSQL_ROW其实是char **,可以当成一个二维数组来用

    MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
    
    • 1

    在这里插入图片描述

    (10) 关闭mysql链接mysql_close

    void mysql_close(MYSQL *sock);
    
    • 1

    另外,mysql C api还支持事务等常用操作,大家下来自行了解:

    my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
    my_bool STDCALL mysql_commit(MYSQL * mysql);
    my_bool STDCALL mysql_rollback(MYSQL * mysql);
    
    • 1
    • 2
    • 3

    3. 测试代码

    前提:makefile文件的写法我在环境设置部分已经说明,在使用此代码测试前要为自己创建一个mysql下的普通账号并赋予其对特定数据库的所有权限,在我上一个博客中:

    MySQL用户管理_Ryujianli的博客-CSDN博客

    #include
    #include
    #include
    
    const std::string host="127.0.0.1";
    const std::string user="user_l";
    const std::string password="1003898";
    const std::string db="conn";
    const unsigned int port=3306;
    
    int main()
    {
        // std::cout<<"mysql client version: "<
    
        MYSQL* my=mysql_init(nullptr);
        if(nullptr ==my)
        {
            std::cerr<< "init MySQL error" <<std::endl;
            return 1;
        }
    
        if(mysql_real_connect(my,host.c_str(),user.c_str(),password.c_str(),db.c_str(),port,nullptr,0)==nullptr)
        {
            std::cerr<<"connect MySQL error"<<std::endl;
            return 2;
        }
    
        mysql_set_character_set(my,"utf8");
    
        // 增删改简单处理
    
        // std::string sql="insert into user (name,age,telephone) values ('张三', 19, '1523467')";
        // std::string sql="insert into user (name,age,telephone) values ('kitty', 29, '13234567')";
        // std::string sql="update user set name='Jimmy' where id=2";
        // std::string sql="delete from user where id=3";
    
        // 查的处理
        std::string sql="select * from user";
    
        int n=mysql_query(my,sql.c_str());
        if(n==0)
            std::cout<<sql<< " success " <<std::endl;
        else
        {
            std::cout<<sql<< " failed " <<std::endl;
            return 3;
        }
    
        MYSQL_RES*res=mysql_store_result(my);
        if(nullptr==res)
        {
            std::cerr<< "mysql_store_result error" <<std::endl;
            return 3;
        }
    
        // 全部都是和结果集有关的, res
        int rows=mysql_num_rows(res);
        int fields=mysql_num_fields(res);
    
        std::cout<< "行: "<<rows<<std::endl;
        std::cout<< "列: "<<fields<<std::endl;
    
        // 属性
        MYSQL_FIELD*fields_array=mysql_fetch_fields(res);
        for(int i=0;i<fields;++i)
        {
            std::cout<<fields_array[i].name<< "\t";
        }
        std::cout<< "\n";
    
        // 内容
        for(int i=0;i<rows;++i)
        {
            MYSQL_ROW row= mysql_fetch_row(res);    // char**
            for(int j=0;j<fields;++j)
            {
                std::cout<<row[j]<< "\t";    // *(row+j)
            }
            std::cout<< "\n";
        }  
        std::cout<<fields_array[0].db<<" "<<fields_array[0].table<<std::endl;
    
        // std::cout<<"connect success"<
    
        mysql_free_result(res);
        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
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
  • 相关阅读:
    IC设计高级017:控制类寄存器2种实现方式
    容错计算和恢复
    Vue事件机制和事件修饰符
    Nacos Discovery服务治理
    前后端分离项目,vue+uni-app+php+mysql订座预约小程序系统 开题报告
    计算机毕业设计Java网上课程资源管理系统(源码+系统+mysql数据库+Lw文档)
    DNS轮询是什么
    《Deep Convolution Neural Networks for Twitter Sentiment Analysis》文献研读
    SQL server创建数据库
    【毕业设计】基于 STM32 的自动泊车系统 -智能小车 - 物联网单片机
  • 原文地址:https://blog.csdn.net/Ryujianli/article/details/132798795