相关推荐recommended
【MySQL】使用C语言连接数据
作者:mmseoamin日期:2024-04-30

使用C语言连接数据

  • 一、引入库
    • 1、手动下载库
    • 2、上传至云服务器
    • 二、使用库
      • 1、简单示例
      • 2、连接数据库
      • 3、下发SQL请求
      • 4、获取查询结果
      • 三、事务操作
      • 四、错误处理

        一、引入库

        要使用C语言连接MySQL,需要使用MySQL官网提供的库。

        • 方式一

          如果我们使用的是Linux系统的话我们可以直接使用,下面的命令安装MySQL给我们提供的官方库:

          sudo yum install mysql-community-devel
          

          下载完以后我们可以在/usr/include/mysql/(其他系统可能会有差别)看到头文件:

          ls /usr/include/mysql/
          

          【MySQL】使用C语言连接数据,在这里插入图片描述,第1张

          在/usr/lib64/mysql/看到对应的库:

          ls /usr/lib64/mysql/
          

          【MySQL】使用C语言连接数据,在这里插入图片描述,第2张

          • 方式二

            1、手动下载库

            首先,进入MySQL官网,选择DOWNLOADS(下载),然后点击MySQL Community (GPL) Downloads。如下:

            【MySQL】使用C语言连接数据,在这里插入图片描述,第3张

            接下来选择Download Archives

            【MySQL】使用C语言连接数据,在这里插入图片描述,第4张

            最后选择适合自己平台的mysql connect库,然后点击下载就行了。如下:

            【MySQL】使用C语言连接数据,在这里插入图片描述,第5张

            2、上传至云服务器

            因为这里我要在Linux服务器上使用,所以将其上传到云服务器,我准备将下载的库文件存放在一个名为mysqllib的目录下。

            使用rz 命令将刚才下载的库文件上传到云服务器。如下:

            rz 
            

            【MySQL】使用C语言连接数据,在这里插入图片描述,第6张

            然后使用tar命令将压缩包解压到当前目录下。如下:

            tar -xzf mysql-connector-c-6.1.11-linux-glibc2.12-x86_64.tar.gz
            

            【MySQL】使用C语言连接数据,在这里插入图片描述,第7张

            为了方便使用我们将名称更改一下:

            mv mysql-connector-c-6.1.11-linux-glibc2.12-x86_64 mysql-connector-c
            

            【MySQL】使用C语言连接数据,在这里插入图片描述,第8张

            进入解压后的目录当中,可以看到有一个include子目录和一个lib子目录。如下:

            【MySQL】使用C语言连接数据,在这里插入图片描述,第9张

            其中,include目录下存放的一堆头文件。如下:

            【MySQL】使用C语言连接数据,在这里插入图片描述,第10张

            而lib目录下存放的就是动静态库。如下:

            【MySQL】使用C语言连接数据,在这里插入图片描述,第11张


            由于我们要使用的是动态库,所以当我们使用gcc编译时要使用-I命令后面跟对应的头文件路径,使用-L指定库的路径,使用-l连接具体的库。(这里为-l mysqlclient)

            二、使用库

            mysqlclient给我们提供了许多API,其官方手册中可以看到许多细节内容,此外还有一些关于mysqlclient库中一些结构体对象的含义可以看这里。

            1、简单示例

            为了确保我们能够正常的将库引入进我们的代码中,我们可以先使用mysql_get_client_info()函数来进行测试。

            【MySQL】使用C语言连接数据,在这里插入图片描述,第12张

            • 此函数的功能就是返回一个记录了mysql客户端版本库的字符串。

              代码如下:

              #include 
              #include 
              int main()
              {
                  const char* str = mysql_get_client_info();
                  printf("%s\n", str);
                  return 0;
              }
              

              为了方便后续重复编译源文件,可以在项目目录下创建一个Makefile,Makefile当中的内容如下:

              【MySQL】使用C语言连接数据,在这里插入图片描述,第13张

              说明:

              • Makefile是一个文件,里面编写了一些关于进行编译和链接的命令,有了它我们就可以使用make命令直接编译整个文件。
              • 这里我们没有指定头文件的搜索路径,因为我们mysql头文件在/usr/inclue目录下,这是gcc编译时的默认搜索路径,所以我们不需要指定。

                编译运行成功:

                【MySQL】使用C语言连接数据,在这里插入图片描述,第14张

                从运行结果我们能够看出我们使用的客户端库版本是5.744,此外我们还可以使用ldd命令查看程序运行所需要的库:

                【MySQL】使用C语言连接数据,在这里插入图片描述,第15张

                至此库已经成功被引入,我们下面正式开始学习库接口的使用。

                2、连接数据库

                创建MYSQL对象

                在连接数据库之前,需要先创建一个MySQL对象,创建MySQL对象的函数如下:

                【MySQL】使用C语言连接数据,在这里插入图片描述,第16张

                说明:

                • 该函数用来分配或者初始化一个MySQL对象,用于连接MySQL服务器。
                • 如果传入的参数是NULL,那么mysql_init将自动为你分配一个MySQL对象并返回。
                • 如果传入的参数是一个地址,那么mysql_init将在该地址处帮你完成初始化。

                  MYSQL对象中包含了各种信息,其类型定义如下:

                  【MySQL】使用C语言连接数据,在这里插入图片描述,第17张

                  • MYSQL对象中的methods变量是一个结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。

                    连接数据库

                    创建完MySQL对象后就可以连接数据库了,连接数据库的函数如下:

                    【MySQL】使用C语言连接数据,在这里插入图片描述,第18张

                    参数说明:

                    • mysql: 表示在连接数据库前,调用mysql_init函数创建的MySQ`对象。
                    • host: 表示需要连接的MySQL服务器的IP地址,127.0.0.1或者localhost表示连接本地MySQL服务器。
                    • user: 表示连接MySQL服务器时,所使用用户的用户名。
                    • passwd: 表示连接MySQL服务器时,所使用用户的密码
                    • db: 表示连接MySQL服务器后,需要使用的数据库。
                    • port: 表示连接的MySQL服务器,所对应的端口号。
                    • unix_socket: 表示连接时使用的套接字或命名管道,设置为NULL表示使用TCP/IP进行连接。
                    • clientflag: 可以设置为多个标志位的组合,表示允许特定的功能,这里我们不使用所以设置为0。

                      返回值:

                      • 如果连接数据库成功,则返回一个MySQL对象,该对象与第一个参数的值相同。
                      • 如果连接数据库失败,则返回NULL。

                        设置连接的编码格式

                        当我们使用mysql_real_connect建立好链接之后,获取英文字符是没有问题,但是如果是获取中文则是乱码,因为MySQL默认连接的编码格式采用latin1,所以我们需要设置连接的编码格式。

                        【MySQL】使用C语言连接数据,在这里插入图片描述,第19张

                        参数:

                        • mysql: 表示在连接数据库前,调用mysql_init函数创建的MySQL对象。
                        • csname: 表示要设置的编码格式,如"utf8"。

                          返回值:

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

                            关闭数据库连接

                            与数据库交互完毕后,需要关闭数据库连接释放资源,关闭数据库连接的函数如下:

                            【MySQL】使用C语言连接数据,在这里插入图片描述,第20张

                            说明:

                            • 该函数的参数,就是连接数据库前调用mysql_init创建的MySQL对象。

                              比如使用如下代码连接我的MySQL服务器:

                              #include 
                              #include 
                              #include 
                              #include 
                              const char* host = "localhost";
                              const char* user = "qiling";
                              const char* password = "123456";
                              const char* db = "db1";
                              u_int32_t port = 3309;
                              int main()
                              {
                                  // 1.初始化MYSQL对象
                                  MYSQL* my = mysql_init(NULL);
                                  if (!my)
                                  {
                                      perror("mysql_init fail: ");
                                      exit(errno);
                                  }
                                  // 2.连接MySQL服务器
                                  if (!mysql_real_connect(my, host, user, password, db, port, NULL, 0))
                                  {
                                      perror("mysql_real_connect fail: ");
                                      exit(errno);
                                  }
                                  // 3. 设置连接的编码格式
                                  if (0 != mysql_set_character_set(my, "utf8"))
                                  {
                                      perror("mysql_set_character_set fail: ");
                                      exit(errno);
                                  }
                                  // 休眠10s,方便我们观察实验现象
                                  sleep(10);
                                  // 4. 关闭连接,释放对象
                                  mysql_close(my);
                                  
                                  return 0;
                              }
                              

                              我们编译运行此代码,同时让root用户使用show processlist命令查看登录状况。

                              【MySQL】使用C语言连接数据,在这里插入图片描述,第21张

                              可以看到,确实有一个叫qiling的用户连接了数据库,说明我们的连接成功了。

                              3、下发SQL请求

                              与数据库建立连接期间,就可以向MySQL服务器下发SQL请求,下发SQL请求的函数如下:

                              【MySQL】使用C语言连接数据,在这里插入图片描述,第22张

                              参数:

                              • mysql: 表示在连接数据库前,调用mysql_init函数创建的MySQL对象。
                              • stmt_str: 表示向MySQL服务器下发的SQL请求,SQL最后可以不带分号。

                                返回值:

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

                                  测试表结构

                                  这个账户表中我们设置主键为id并且自增,然后主要信息包含两个字段,name名称,balance余额。

                                  【MySQL】使用C语言连接数据,在这里插入图片描述,第23张

                                  通过下面的代码,我们进行测试:

                                  • 先向这个数据库中插入两条信息:Peter,2398.4 ;张三, 3476.9。 (增)
                                    #include 
                                    #include 
                                    #include 
                                    #include 
                                    const char* host = "localhost";
                                    const char* user = "qiling";
                                    const char* password = "123456";
                                    const char* db = "db1";
                                    u_int32_t port = 3309;
                                    int main()
                                    {
                                        // 1.初始化MYSQL对象
                                        MYSQL* my = mysql_init(NULL);
                                        if (!my)
                                        {
                                            perror("mysql_init fail: ");
                                            exit(errno);
                                        }
                                        // 2.连接MySQL服务器
                                        if (!mysql_real_connect(my, host, user, password, db, port, NULL, 0))
                                        {
                                            perror("mysql_real_connect fail: ");
                                            exit(errno);
                                        }
                                        // 3. 设置连接的编码格式
                                        if (0 != mysql_set_character_set(my, "utf8"))
                                        {
                                            perror("mysql_set_character_set fail: ");
                                            exit(errno);
                                        }
                                        // 4.下达SQL指令
                                        // 4.1 增加信息
                                        const char* sql = "insert into account(name, balance) values('Peter', 2398.4),('张三',3476.9)";
                                        if (0 != mysql_query(my, sql))
                                        {
                                            perror("mysql_query fail: ");
                                            exit(errno);
                                        }
                                        // 5. 关闭连接,释放对象
                                        mysql_close(my);
                                        
                                        return 0;
                                    }
                                    

                                    编译运行我们的代码,发现确实向表中新插入了两条数据,并且数据没有乱码。

                                    【MySQL】使用C语言连接数据,在这里插入图片描述,第24张

                                    • 然后将张三的名称改为Alex。(改)
                                      ....
                                      const char* sql = "update account set name = 'Alex' where name='张三'";
                                      ....
                                      

                                      【MySQL】使用C语言连接数据,在这里插入图片描述,第25张

                                      • 最后删除Peter的这条记录。 (删)
                                        ....
                                        const char* sql = "delete from account where name = 'Peter'";
                                        ...
                                        

                                        【MySQL】使用C语言连接数据,在这里插入图片描述,第26张

                                        至此为止我们现在增删改的操作都能够进行了!

                                        4、获取查询结果

                                        数据存储

                                        当我们对数据库中的数据进行增删改操作时,我们只关心操作有没有成功。

                                        而对数据库中的数据进行查询操作时,除了需要知道有没有成功,还需要获取查询结果。

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

                                        【MySQL】使用C语言连接数据,在这里插入图片描述,第27张

                                        说明:

                                        • 该函数会调用指定MySQL对象中 st_mysql_methods中的read_rows函数指针来获取查询的结果,并将获取到的查询结果保存到MYSQL_RES变量中进行返回。
                                        • 需要注意的是,MYSQL_RES变量的内存空间是malloc出来的,因此在使用完后需要调用mysql_free_result函数进行释放,否则会造成内存泄露。

                                          MYSQL_RES变量中保存了查询得到的各种信息,其类型定义如下:

                                          【MySQL】使用C语言连接数据,在这里插入图片描述,第28张

                                          获取查询结果的行数

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

                                          【MySQL】使用C语言连接数据,在这里插入图片描述,第29张

                                          说明:

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

                                            获取查询结果的列数

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

                                            【MySQL】使用C语言连接数据,在这里插入图片描述,第30张

                                            说明:

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

                                              获取查询结果的列属性

                                              【MySQL】使用C语言连接数据,在这里插入图片描述,第31张

                                              说明:

                                              • 该函数将会从指定的MYSQL_RES对象中,获取查询结果的列属性。

                                                mysql_fetch_fields函数将会返回一组MYSQL_FIELD对象,这组对象的地址是连续的,每个MYSQL_FIELD对象中保存着对应列的各种列属性,其类型定义如下:

                                                【MySQL】使用C语言连接数据,在这里插入图片描述,第32张

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

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

                                                【MySQL】使用C语言连接数据,在这里插入图片描述,第33张

                                                说明:

                                                • 该函数将会从指定的MYSQL_RES对象中,获取查询结果中的一行数据。
                                                • 该函数内部会记录当前我们访问到了哪一行,不需要我们手动控制,我们只需要不断调用就能拿到所有的行数据。

                                                  MYSQL_ROW对象中保存着一行数据,这一行数据中可能包含多个字符串,对应就是这行数据中的多个列信息,因此MYSQL_ROW本质就是char**类型,我们将其可以当成一个char*的指针数组,其类型定义如下:

                                                  【MySQL】使用C语言连接数据,在这里插入图片描述,第34张

                                                  【MySQL】使用C语言连接数据,在这里插入图片描述,第35张

                                                  释放结果集

                                                  在前面我们说过MYSQL_RES变量的内存空间是malloc出来的,因此在使用完后需要调用mysql_free_result函数进行释放,否则会造成内存泄露。

                                                  mysql_free_result函数的原型如下:

                                                  【MySQL】使用C语言连接数据,在这里插入图片描述,第36张

                                                  只需要我们传递我们结果集对应的指针就行了

                                                  查询示例

                                                  为了让数据多一些,我们先多插入一些数据:

                                                  【MySQL】使用C语言连接数据,在这里插入图片描述,第37张

                                                  比如查询account表中的数据并进行打印输出。如下:

                                                  #include 
                                                  #include 
                                                  #include 
                                                  #include 
                                                  const char* host = "localhost";
                                                  const char* user = "qiling";
                                                  const char* password = "123456";
                                                  const char* db = "db1";
                                                  u_int32_t port = 3309;
                                                  int main()
                                                  {
                                                      // 1.初始化MYSQL对象
                                                      MYSQL* my = mysql_init(NULL);
                                                      if (!my)
                                                      {
                                                          perror("mysql_init fail: ");
                                                          exit(errno);
                                                      }
                                                      // 2.连接MySQL服务器
                                                      if (!mysql_real_connect(my, host, user, password, db, port, NULL, 0))
                                                      {
                                                          perror("mysql_real_connect fail: ");
                                                          exit(errno);
                                                      }
                                                      // 3. 设置连接的编码格式
                                                      if (0 != mysql_set_character_set(my, "utf8"))
                                                      {
                                                          perror("mysql_set_character_set fail: ");
                                                          exit(errno);
                                                      }
                                                      // 4.下达SQL指令
                                                      const char* sql = "select * from account";
                                                      if (0 != mysql_query(my, sql))
                                                      {
                                                          perror("mysql_query fail: ");
                                                          exit(errno);
                                                      }
                                                      // 5.获得存储结果
                                                      MYSQL_RES* my_res = mysql_store_result(my);
                                                      // 5.1获得结果集中的行数
                                                      my_ulonglong rows = mysql_num_rows(my_res);
                                                      // 5.2获得结果集中的列数
                                                      u_int32_t column = mysql_num_fields(my_res);
                                                      // 5.3获得结果集中的字段属性
                                                      MYSQL_FIELD* filed_array = mysql_fetch_fields(my_res);
                                                      // 5.4获取结果集中的数据,并进行打印
                                                      // 打印字段的属性
                                                      for (int i = 0; i < column; i++)
                                                      {
                                                          printf("%s\t", filed_array[i].name);
                                                      }
                                                      printf("\n");
                                                      printf("----------------------------\n");
                                                      // 打印字段的数据
                                                      for (int i = 0; i < rows; i++)
                                                      {
                                                          MYSQL_ROW row_data = mysql_fetch_row(my_res);
                                                          for (int j = 0; j < column; j++)
                                                          {
                                                              printf("%s\t", row_data[j]);
                                                          }
                                                          printf("\n");
                                                      }
                                                      // 6.释放结果集
                                                      mysql_free_result(my_res);
                                                      // 7. 关闭连接,释放对象
                                                      mysql_close(my);
                                                      return 0;
                                                  }
                                                  

                                                  【MySQL】使用C语言连接数据,在这里插入图片描述,第38张

                                                  三、事务操作

                                                  对于事务的操作我们也可以使用mysql_query()函数进行开启一个事务,然后进行处理事务,下面我们介绍一些关于控制事务操作的一些API。

                                                  设置事务提交模式

                                                  【MySQL】使用C语言连接数据,在这里插入图片描述,第39张

                                                  参数:

                                                  • mysql,我们使用mysql_init()函数创建出来的mysql对象

                                                  • 如果 mode 为 1,则将自动提交模式设置为 on,如果 mode 为 0,则将自动提交模式设置为 off。

                                                    返回值:

                                                    • 如果成功,返回0,如果出现错误,返回非0值。

                                                      提交事务

                                                      【MySQL】使用C语言连接数据,在这里插入图片描述,第40张

                                                      参数:

                                                      • mysql,我们使用mysql_init()函数创建出来的mysql对象

                                                        返回值:

                                                        • 如果成功,返回0,如果出现错误,返回非0值。

                                                          事务回滚

                                                          【MySQL】使用C语言连接数据,在这里插入图片描述,第41张

                                                          参数:

                                                          • mysql,我们使用mysql_init()函数创建出来的mysql对象

                                                            返回值:

                                                            • 如果成功,返回0,如果出现错误,返回非0值。

                                                              四、错误处理

                                                              返回错误的描述

                                                              【MySQL】使用C语言连接数据,在这里插入图片描述,第42张

                                                              参数:

                                                              • mysql,我们使用mysql_init()函数创建出来的mysql对象

                                                                返回值

                                                                • 返回错误的描述对应的字符串

                                                                  返回错误的编号

                                                                  【MySQL】使用C语言连接数据,在这里插入图片描述,第43张

                                                                  参数:

                                                                  • mysql,我们使用mysql_init()函数创建出来的mysql对象

                                                                    返回值

                                                                    • 返回错误的编号

                                                                      下面的代码我们

                                                                      • 先开启一个事务,然后插入一条数据smith, 3478.9。
                                                                      • 然后修改金额为8907.6
                                                                      • 然后提交该事务。
                                                                      • 之后我们再次开启一个事务,
                                                                      • 然后再插入一条数据Lisa, 4588.7。
                                                                      • 最后进行数据回滚。

                                                                        根据代码我们最后插入的数据应该只有smith,8907.6,这是我们表的初始状态:

                                                                        【MySQL】使用C语言连接数据,在这里插入图片描述,第44张

                                                                        #include 
                                                                        #include 
                                                                        #include 
                                                                        #include 
                                                                        const char* host = "localhost";
                                                                        const char* user = "qiling";
                                                                        const char* password = "123456";
                                                                        const char* db = "db1";
                                                                        u_int32_t port = 3309;
                                                                        int main()
                                                                        {
                                                                            // 1.初始化MYSQL对象
                                                                            MYSQL* my = mysql_init(NULL);
                                                                            if (!my)
                                                                            {
                                                                                perror("mysql_init fail: ");
                                                                                exit(errno);
                                                                            }
                                                                            // 2.连接MySQL服务器
                                                                            if (!mysql_real_connect(my, host, user, password, db, port, NULL, 0))
                                                                            {
                                                                                perror("mysql_real_connect fail: ");
                                                                                exit(errno);
                                                                            }
                                                                            // 3. 设置连接的编码格式
                                                                            if (0 != mysql_set_character_set(my, "utf8"))
                                                                            {
                                                                                perror("mysql_set_character_set fail: ");
                                                                                exit(errno);
                                                                            }
                                                                        	// 4.下达SQL指令 开启事务
                                                                            mysql_autocommit(my, 1);
                                                                            mysql_query(my, "begin");
                                                                            mysql_query(my, "insert into account(name, balance) values('smith', 3478.9)");
                                                                            mysql_query(my, "update account set balance=8907.6 where name='smith'");
                                                                            mysql_commit(my);
                                                                            mysql_query(my, "begin");
                                                                            mysql_query(my, "insert into account(name, balance) values('lisa', 4588.7)");
                                                                            mysql_rollback(my);
                                                                            // 5. 关闭连接,释放对象
                                                                            mysql_close(my);
                                                                            return 0;
                                                                        }
                                                                        

                                                                        最后的运行结果符合我们的预期:

                                                                        【MySQL】使用C语言连接数据,在这里插入图片描述,第45张