MySQL使用C语言连接

一、准备工作

要使用 C 语言连接 MySQL,我们需要做一些准备工作:

  • 保证 MySQL 服务有效。
  • 在 MySQL 官网上下载适合自己平台的 MySQL Connector/C 库。

对应的网址:https://downloads.mysql.com/archives/c-c/在这里插入图片描述

把压缩包下载下来后,将其解压到当前目录。

在这里插入图片描述

进入解压后的目录后,可以看到该目录下的 include 目录和 lib 目录。
其中,include 目录下存放的是头文件(方法的声明),lib 目录下存放的是动静态库(方法的实现,打包成库)。

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

必须要让程序在运行时能找到上述的库文件!


为了验证库的引入是否成功,可以通过调用其中的mysql_get_client_info函数来验证。

该函数的作用是获取 MySQL 客户端的版本信息。

#include <iostream>
#include <cstdio>
#include <mysql/mysql.h>

int main()
{
    std::cout << "client version: " << mysql_get_client_info() << std::endl;

    return 0;
}

运行结果:
在这里插入图片描述

程序成功运行,说明库已经成功被引入了,至此库的引入工作已经做完。

二、MySQL 的 C 语言接口

1. mysql_init

MYSQL *mysql_init(MYSQL *mysql);

mysql_init函数的作用:创建一个 MYSQL 对象(该对象用于连接数据库)。

mysql_init函数的参数:
 ① mysql:MYSQL 结构体指针,一般设置为 NULL 。

mysql_init函数的返回值:
 ① 成功,返回一个指向 MYSQL 对象的指针。
 ② 失败,返回 NULL 。


MYSQL 对象的定义如下:

typedef struct st_mysql
{
  NET		net;			/* Communication parameters */
  unsigned char	*connector_fd;		/* ConnectorFd for SSL */
  char		*host,*user,*passwd,*unix_socket,*server_version,*host_info;
  char          *info, *db;
  struct charset_info_st *charset;
  MYSQL_FIELD	*fields;
  MEM_ROOT	field_alloc;
  my_ulonglong affected_rows;
  my_ulonglong insert_id;		/* id if insert on table with NEXTNR */
  my_ulonglong extra_info;		/* Not used */
  unsigned long thread_id;		/* Id for connection in server */
  unsigned long packet_length;
  unsigned int	port;
  unsigned long client_flag,server_capabilities;
  unsigned int	protocol_version;
  unsigned int	field_count;
  unsigned int 	server_status;
  unsigned int  server_language;
  unsigned int	warning_count;
  struct st_mysql_options options;
  enum mysql_status status;
  my_bool	free_me;		/* If free in mysql_close */
  my_bool	reconnect;		/* set to 1 if automatic reconnect */

  /* session-wide random string */
  char	        scramble[SCRAMBLE_LENGTH+1];
  my_bool unused1;
  void *unused2, *unused3, *unused4, *unused5;

  LIST  *stmts;                     /* list of all statements */
  const struct st_mysql_methods *methods;
  void *thd;
  /*
    Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag 
    from mysql_stmt_close if close had to cancel result set of this object.
  */
  my_bool *unbuffered_fetch_owner;
  /* needed for embedded server - no net buffer to store the 'info' */
  char *info_buffer;
  void *extension;
} MYSQL;

MYSQL 对象里有很多连接基本参数,它也包含了一个叫 st_mysql_methods 的结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。

2. mysql_real_connect

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_real_connect函数的作用:连接数据库。

mysql_real_connect函数的参数:
 ① mysql:MYSQL 对象指针。
 ② host:要连接的 MySQL 服务器的 IP 地址。
 ③ user:用户名,以哪个用户身份连接。
 ④ passwd:用户密码。
 ⑤ db:要连接的数据库。
 ⑥ port:要连接的 MySQL 服务器的端口号。
 ⑦ unix_socket:通常设置为 NULL 。
 ⑧ clientflag:通常设置为 0 。

mysql_real_connect函数的返回值:
 ① 成功,返回一个指向 MYSQL 对象的指针,与第一个参数 mysql 的值相同。
 ② 失败,返回 NULL 。

3. mysql_close

void mysql_close(MYSQL *sock);

mysql_close函数的作用:关闭数据库连接。

mysql_close函数的参数:
 ① sock:MYSQL 对象指针。

mysql_close函数的返回值:无。

4. mysql_set_character_set

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

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

mysql_set_character_set函数的作用:设置编码格式。

mysql_set_character_set函数的参数:
 ① mysql:MYSQL 对象指针。
 ② csname:要设置成哪种字符集。

mysql_set_character_set函数的返回值:
 ① 成功,为 0 。
 ② 失败,为非 0 。

5. mysql_query

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

mysql_query函数的作用:下发 SQL 请求。

mysql_query函数的参数:
 ① mysql:MYSQL 对象指针。
 ② q:要执行的 SQL 语句(语句结尾可以不带分号)。

mysql_query函数的返回值:
 ① 成功,为 0 。
 ② 失败,为非 0 。

6. mysql_store_result

MYSQL_RES *mysql_store_result(MYSQL *mysql);

mysql_store_result函数的作用:获取查询结果。

mysql_store_result函数的参数:
 ① mysql:MYSQL 对象指针。

mysql_store_result函数的返回值:
 ① 成功,返回一个指向 MYSQL_RES 对象的指针。
 ② 失败,返回 NULL 。

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

该函数会 malloc 出一个 MYSQL_RES 结构体变量,将获取到的查询结果保存到该变量中,最后返回该变量的指针。

由于 MYSQL_RES 的内存空间是 malloc 出来的,所以在使用完之后一定要记得调用 free 函数来释放对应的内存空间,否则会造成内存泄漏。


执行完mysql_store_result以后,其实要查询的数据都已经在 MYSQL_RES 变量中了,下面的函数基本就是读取 MYSQL_RES 中的数据,参数都是 MYSQL_RES 对象指针:

// 获取结果的行数
my_ulonglong mysql_num_rows(MYSQL_RES *res);

// 获取结果的列数
unsigned int mysql_num_fields(MYSQL_RES *res);

// 获取结果的列属性
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);

// 获取结果中的一行记录
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

关于mysql_fetch_row函数的返回值 MYSQL_ROW:
MYSQL_ROW,即结果中的一行记录,对应着多个列信息,实际上就是一个字符串数组,因此,MYSQL_ROW 类型,本质就是 char** 类型,其定义如下:

typedef char **MYSQL_ROW;		/* return data as array of strings */

三、使用示例

1.连接数据库和关闭数据库连接

mysql_real_connectmysql_close

#include <iostream>
#include <string>
#include <cstdio>
#include <mysql/mysql.h>

const std::string host = "127.0.0.1";
const std::string user = "skc";
const std::string password = "32aT.&6/1*hqrs/s";
const std::string db = "102_db";
const unsigned int port = 3306;

int main()
{
    // std::cout << "client version: " << mysql_get_client_info() << std::endl;
     
    //0. 创建mysql句柄
    MYSQL *my = mysql_init(nullptr);

    //1. 连接数据库
    if(mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0) == nullptr){
        std::cout << "connect failed" << std::endl;
        return 1;
    }
    std::cout << "connect success" << std::endl;
    
    //2. 访问数据库

    //3. 关闭数据库连接
    mysql_close(my);

    return 0;
}

运行结果:在这里插入图片描述

2.访问数据库

mysql_query

  • 执行 insert 操作:
#include <iostream>
#include <string>
#include <cstdio>
#include <mysql/mysql.h>

const std::string host = "127.0.0.1";
const std::string user = "skc";
const std::string password = "32aT.&6/1*hqrs/s";
const std::string db = "102_db";
const unsigned int port = 3306;

int main()
{
    // std::cout << "client version: " << mysql_get_client_info() << std::endl;
     
    //0. 创建mysql句柄
    MYSQL *my = mysql_init(nullptr);

    //1. 连接数据库
    if(mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0) == nullptr){
        std::cout << "connect failed" << std::endl;
        return 1;
    }
    //1.1: 需要设置连接的编码格式,否则会出现乱码
    mysql_set_character_set(my, "utf8");
    std::cout << "connect success" << std::endl;
    
    //2. 访问数据库
    std::string sql = "insert into mytest values (4, '猪八戒')";
    int res = mysql_query(my, sql.c_str());
    if(res != 0){
        std::cout << "execute: " << sql << " failed" << std::endl;
        return 2;
    }
    std::cout << "execute: " << sql << " success" << std::endl;

    //3. 关闭数据库连接
    mysql_close(my);

    return 0;
}

运行结果:
在这里插入图片描述
执行了 insert 操作。在这里插入图片描述

  • 执行 delete 操作:
std::string sql = "delete from mytest where id=3";

运行结果:
在这里插入图片描述
执行了 delete 操作。
在这里插入图片描述

  • 执行 update 操作:
std::string sql = "update mytest set name='唐僧' where id=2";

运行结果:
在这里插入图片描述
执行了 update 操作。
在这里插入图片描述

  • 执行 select 操作:
#include <iostream>
#include <string>
#include <cstdio>
#include <mysql/mysql.h>

const std::string host = "127.0.0.1";
const std::string user = "skc";
const std::string password = "32aT.&6/1*hqrs/s";
const std::string db = "102_db";
const unsigned int port = 3306;

int main()
{
    // std::cout << "client version: " << mysql_get_client_info() << std::endl;
     
    //0. 创建mysql句柄
    MYSQL *my = mysql_init(nullptr);

    //1. 连接数据库
    if(mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db.c_str(), port, nullptr, 0) == nullptr){
        std::cout << "connect failed" << std::endl;
        return 1;
    }
    //1.1: 需要设置连接的编码格式
    mysql_set_character_set(my, "utf8");
    std::cout << "connect success" << std::endl;
    
    //2. 访问数据库
    // 增删改是最简单的,因为只要sql执行完毕就完了
    // std::string sql = "insert into mytest values (4, '猪八戒')";
    // std::string sql = "delete from mytest where id=3";
    // std::string sql = "update mytest set name='唐僧' where id=2";
    
    //2.1 select 其实是最不好处理的!select sql执行完只是第一步,还需要对数据进一步解析
    //std::string sql = "select * from mytest where id=4";
    //std::string sql = "select name from mytest where id=4";
    std::string sql = "select * from mytest";
    int code = mysql_query(my, sql.c_str());
    if(code != 0){
        std::cout << "execute: " << sql << " failed" << std::endl;
        return 2;
    }
    std::cout << "execute: " << sql << " success" << std::endl;
    //2.2 解析数据 -- 获取行号和列号
    MYSQL_RES *result = mysql_store_result(my);
    int rows = mysql_num_rows(result);
    int cols = mysql_num_fields(result);
    std::cout << "行数:" << rows << ",列数:" << cols << std::endl;

    //2.3 解析数据 -- 获取表中列名 -- 一般不用,仅仅是为了测试代码的完整性
    MYSQL_FIELD *fields = mysql_fetch_fields(result);
    for(int i = 0; i < cols; i++){
        std::cout << fields[i].name << "t";
    }
    std::cout << std::endl;

    //2.4 解析数据 -- 获取表中的数据 -- 重要
    for(int i = 0; i < rows; i++){
        MYSQL_ROW line = mysql_fetch_row(result);  // 获取完整的一行记录(默认从前往后)
        for(int j = 0; j < cols; j++){
            std::cout << line[j] << "t";  // 将一行记录内部的多列字符串依次打印
        }
        std::cout << std::endl;
    }
    free(result);  // 释放内存空间
		
    //3. 关闭数据库连接
    mysql_close(my);

    return 0;
}

运行结果:
在这里插入图片描述对照命令行下的 select 操作,没问题。
在这里插入图片描述

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>