MySQL Connector/C++ API的使用(16)

发布于:2025-07-26 ⋅ 阅读:(13) ⋅ 点赞:(0)


前言

  我们之前一直都是在用命令行来操作数据库,今天我们换一种方式来操作,用编程语言!
  其实,还可以考虑用 图形化GUI页面 来操作,肯定可以的,不过这个我自己也没怎么玩过,可能以后会吧,上网搜索了一下,好像 MySQL Workbench(免费)、Navicat(收费) 这两个还不错,就交由大家自行去掌握了!


一、环境配置

  其实我不太想把配置环境的过程放上来,因为我认为这是不得不品的一环,必须让大家都来尝一口(

  可以先来回顾下这篇文章
  Linux软硬链接和动静态库(20)

  界面应该都是大差不差的,我这里呈现的是我现在这个时间如何下载所需的库文件

  首先,进入MySQL官网,选择DOWNLOADS

在这里插入图片描述

  再点击这个 MySQL Community (GPL) Downloads »

在这里插入图片描述

  再点击这个 Connector/C++

在这里插入图片描述

  再选择适合自己的系统版本直接下载就行了,这个时候你就拿到了包

在这里插入图片描述
  之后就是熟悉的利用 rz -E 把刚刚下载的库文件上传到云服务器,使用 tar 命令将压缩包解压到当前目录下,然后再熟悉的软链接一下,makefile搞一下

  但是今天我想介绍另外一种方法,使用命令行很方便的一种方式

# 下载库文件
sudo apt-get install libmysqlclient-dev   
sudo apt-get install libmysqlcppconn-dev

# 查看头文件路径
dpkg -L libmysqlclient-dev

  直接一键下好,原理由DS大人给出如下:

在这里插入图片描述

二、一些API的体验

创建MySQL对象

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

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

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

typedef struct 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 *charset;
  MYSQL_FIELD *fields;
  struct MEM_ROOT *field_alloc;
  uint64_t affected_rows;
  uint64_t insert_id;      /* id if insert on table with NEXTNR */
  uint64_t 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;
  enum enum_resultset_metadata resultset_metadata;
  bool free_me;   /* If free in mysql_close */
  bool reconnect; /* set to 1 if automatic reconnect */

  /* session-wide random string */
  char scramble[SCRAMBLE_LENGTH + 1];

  LIST *stmts; /* list of all statements */
  const struct 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.
  */
  bool *unbuffered_fetch_owner;
  void *extension;
} MYSQL;
  • MYSQL对象中的 methods 变量是一个结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。

连接数据库

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

MYSQL *STDCALL 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_init 函数创建的 MySQL 对象。
  • host: 表示需要连接的 MySQL 服务器的IP地址, “127.0.0.1” 表示连接本地 MySQL 服务器。
  • user: 表示连接 MySQL 服务器时,所使用用户的用户名。
  • passwd: 表示连接 MySQL 服务器时,所使用用户的密码
  • db: 表示连接 MySQL 服务器后,需要使用的数据库。
  • port: 表示连接的 MySQL 服务器,所对应的端口号。
  • unix_socket: 表示连接时应该使用的套接字或命名管道,通常设置为 NULL 。
  • clientflag: 可以设置为多个标志位的组合,表示允许特定的功能,通常设置为0。

返回值说明:

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

关闭数据库连接

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

void mysql_close(MYSQL *sock);
  • 该函数的参数,就是连接数据库前调用 mysql_init 创建的 MySQL 对象。
  • 如果传入的 MySQL 对象是 mysql_init 自动创建的,那么调用 mysql_close 时就会释放这个对象。

下发SQL请求

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

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

参数说明:

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

返回值说明:

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

统一编码格式

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

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

参数说明:

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

返回值说明:

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

获取查询结果

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

MYSQL_RES* mysql_store_result(MYSQL *mysql);
  • 该函数会调用指定 MySQL 对象中对应的函数指针来获取查询结果,并将获取到的查询结果保存到 MYSQL_RES 变量中进行返回。
  • 需要注意的是,MYSQL_RES 变量的内存空间是 malloc 出来的,因此在使用完后需要调用 free 函数进行释放,否则会造成内存泄露
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;

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

my_ulonglong mysql_num_rows(MYSQL_RES *res);

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

unsigned int mysql_num_fields(MYSQL_RES *res);

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

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

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

MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES *res);

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

实际示例

  我们现在来一个实际例子,你就明白了,我现在在 Xshell 里面登录一个账户 connector 并且使用数据库 connector 再查询表 user

在这里插入图片描述

  接着我在 Vscode 里面写了以下代码

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

const std::string host = "127.0.0.1";
const std::string user = "connector";
const std::string passwd = "@Lhq123456";
const std::string db = "conn";
const unsigned int port = 3306;

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

    MYSQL* my = mysql_init(nullptr);

    if (my == nullptr)
    {
        std::cerr << "init MySQL error" << std::endl;
        return 1;
    }

    if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.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 = "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 (res == nullptr)
    {
        std::cerr << "mysql_store_result error" << std::endl;
        return 4;
    }

    // "这个res有点像句柄"
    my_ulonglong rows = mysql_num_rows(res);
    my_ulonglong fields = mysql_num_fields(res);

    std::cout << "行: " << rows << std::endl;
    std::cout << "列: " << fields << std::endl;

    // 属性
    MYSQL_FIELD* fields_array = mysql_fetch_fields(res);
    for (my_ulonglong i = 0 ; i < fields ; i++)
    {
        std::cout << fields_array[i].name << "\t";
    }
    std::cout << std::endl;

    // 内容
    for (my_ulonglong i = 0 ; i < rows ; i++)
    {
        MYSQL_ROW row = mysql_fetch_row(res);
        for (my_ulonglong j = 0 ; j < fields ; j++)
        {
            std::cout << row[j] << "\t";
        }
        std::cout << std::endl;
    }

    // std::string sql;
    // while (true)
    // {
    //     std::cout << "MySQL >>> ";
    //     if (!std::getline(std::cin, sql) || sql == "quit") 
    //     {
    //         std::cout << "bye bye" << std::endl;
    //         break;
    //     }

    //     int n = mysql_query(my, sql.c_str());
    //     if (n == 0)
    //     {
    //         std::cout << sql << "  success: " << n << std::endl;
    //     }
    //     else
    //     {
    //         std::cerr << sql << "  failed:  " << n << std::endl;
    //     }
    // } 
    
    // std::cout << "connect success" << std::endl;

    mysql_free_result(res);
    mysql_close(my);

    return 0;
}

  接着 make 编译以下,运行 ./mytest,理所应当的查询结果如下:

在这里插入图片描述


总结

  至此差不多 MySQL 的学习就告一段终了~
  但是感概要学的还有好多啊,什么 Docker、Redis、Qt,甚至前端我也想学一学,项目也想做,下一步该学些什么呢,害,走一步是一步吧,先脚踏实地的干着再说~
  想了一下,还是先把 Linux网络部分 先学完吧,其实我是那一块被干碎了心塞中途跳车学了下 MySQL 缓冲一下,这下又要开始痛苦网络了,哎,我们未来再见!


网站公告

今日签到

点亮在社区的每一天
去签到