MySQL Connector/C API的使用

目录

前言

一些API的体验

创建MySQL对象

连接数据库

关闭数据库连接

下发SQL请求

统一编码格式

获取查询结果

实际示例

题外话:图形化界面

尾声


前言

ok,我们来到了mysql基础的最后一篇,其实我也没有想到我的mysql的博客会比网络先更完,明明网络是更早学的qwq,主要还是网络后面复习需要一些时间,没mysql复习的这么快吧,当然这个专栏可能后面还会在我继续学了mysql更深层次的一些内容后继续更新,话不多说,让我们开始mysql基础的最后一篇的旅程

我们之前一直都是在用命令行来操作数据库,今天我们换一种方式来操作,用编程语言!

配置的话也非常简单,几行命令就解决啦

bash 复制代码
# 下载库文件
sudo apt-get install libmysqlclient-dev   
sudo apt-get install libmysqlcppconn-dev
​
# 查看头文件路径
dpkg -L libmysqlclient-dev

一些API的体验

首先在使用这些api之前肯定是要包含一下对应的头文件的------ #include <mysql/mysql.h>

然后在编译时要带上 -L/usr/lib64/mysql/ 和 -lmysqlclient 让系统知道要连的是在/usr/lib64/mysql/路径下的mysqlclient库

创建MySQL对象

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

cpp 复制代码
MYSQL* mysql_init(MYSQL *mysql);
  • 该函数用来分配或者初始化一个 MySQL 对象,用于连接 MySQL 服务器。

  • 如果传入的参数是 nullptr ,那么 mysql_init 将自动为你分配一个 MySQL 对象并返回。

  • 如果传入的参数是一个地址,那么 mysql_init 将在该地址处帮你完成初始化。

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

cpp 复制代码
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 对象后就可以连接数据库了,连接数据库的函数如下:

cpp 复制代码
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 。

关闭数据库连接

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

cpp 复制代码
void mysql_close(MYSQL *mysql);
  • 该函数的参数,就是连接数据库前调用 mysql_init 创建的 MySQL 对象。

  • 如果传入的 MySQL 对象是 mysql_init 自动创建的,那么调用 mysql_close 时就会释放这个对象。

下发SQL请求

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

cpp 复制代码
int mysql_query(MYSQL *mysql, const char *q);

参数说明:

  • mysql: 表示在连接数据库前,调用 mysql_init 函数创建的 MySQL 对象。

  • q: 表示向MySQL服务器下发的 SQL 请求,SQL 最后可以不带分号。

返回值说明:

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

统一编码格式

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

cpp 复制代码
int mysql_set_character_set(MYSQL *mysql, const char *csname);

参数说明:

  • mysql: 表示在连接数据库前,调用 mysql_init 函数创建的 MySQL 对象。

  • csname: 表示要设置的编码格式,如 " utf8 " 。

返回值说明:

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

获取查询结果

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

cpp 复制代码
MYSQL_RES* mysql_store_result(MYSQL *mysql);
  • 该函数会调用指定 MySQL 对象中对应的函数指针来获取查询结果,并将获取到的查询结果保存到 MYSQL_RES 变量中进行返回。

  • 成功返回查询数据的起始地址,失败返回空nullptr

  • 需要注意的是,MYSQL_RES 变量的内存空间是 malloc 出来的,因此在使用完后需要调用 free 函数进行释放,否则会造成内存泄露

cpp 复制代码
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;

这里不要使用原生的free或者delete来进行释放,而是使用mysql给我们提供的**mysql_free_result(MYSQL_RES* res);**接口进行释放

可以这样来理解res:

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

cpp 复制代码
my_ulonglong mysql_num_rows(MYSQL_RES *res);

\^: 这个my_ulonglong其实就是:typedef uint64_t my_ulonglong;

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

cpp 复制代码
unsigned int mysql_num_fields(MYSQL_RES *res);

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

cpp 复制代码
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

它会返回一个MYSQL_ROW变量,MYSQL_ROW其实就是char **,遍历时会自动获取遍历到当前行的行数据(因为每次循环会自动向后移动指向下一行),其变量就相对于字符串数组,可以下标访问改行各列元素

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

cpp 复制代码
MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES *res);

其实这个MYSQL_FIELD也是一个结构体类型,其中都是列属性

cpp 复制代码
typedef struct MYSQL_FIELD {
  char *name;               /* Name of column */
  char *org_name;           /* Original column name, if an alias */
  char *table;              /* Table of column if column was a field */
  char *org_table;          /* Org table name, if table was an alias */
  char *db;                 /* Database for table */
  char *catalog;            /* Catalog for table */
  char *def;                /* Default value (set by mysql_list_fields) */
  unsigned long length;     /* Width of column (create length) */
  unsigned long max_length; /* Max width for selected set */
  unsigned int name_length;
  unsigned int org_name_length;
  unsigned int table_length;
  unsigned int org_table_length;
  unsigned int db_length;
  unsigned int catalog_length;
  unsigned int def_length;
  unsigned int flags;         /* Div flags */
  unsigned int decimals;      /* Number of decimals in field */
  unsigned int charsetnr;     /* Character set */
  enum enum_field_types type; /* Type of field. See mysql_com.h for types */
  void *extension;
} MYSQL_FIELD;

实际示例

我们现在来一个实际例子来用一下上面了解到的相关接口,现在登录一个账户 mochu 并且使用数据库 conn 再查询表 user

然后我们要编写一段代码来将查询的这个表中内容输出到屏幕上

cpp 复制代码
#include <iostream>
#include <mysql/mysql.h>
​
const std::string host = "127.0.0.1";
const std::string user = "mochu";
const std::string password = "123456";
const std::string dbname = "conn";
const unsigned int port = 3306;
​
int main()
{
    // 1.初始化全局的mysql对象
    // MYSQL*就相对于文件部分的FLIE* ,就是句柄
    MYSQL *mysql = mysql_init(nullptr);
    if (mysql == nullptr)
    {
        std::cerr << "init MYSQL error" << std::endl;
        return 1;
    }
​
    // 2.连接数据库
    if (mysql_real_connect(mysql, host.c_str(), user.c_str(),
                           password.c_str(), dbname.c_str(), port, nullptr, 0) == 0)
    {
        std::cerr << "connect MYSQL error" << std::endl;
        return 2;
    }
    std::cout << "connect MYSQL success" << std::endl;
​
    // 3.设置一下字符集防止乱码
    if (mysql_set_character_set(mysql, "utf8"))
    {
        std::cerr << "set_character error" << std::endl;
        return 3;
    }
    std::cout << "set_character success" << std::endl;
​
    // 4.下发mysql命令
    // std::string sql = "update user set name='李四' where id=2";
    std::string sql = "select * from user";
    // std::string sql = "insert into user (name,age,telphone) values('王五',21,13433322)";
    int n = mysql_query(mysql, sql.c_str());
    if (n == 0)
        std::cout << sql << " success" << std::endl;
    else
        std::cout << sql << " failed" << std::endl;
​
    // 5.获取查询结果到查询集res当中
    MYSQL_RES *res = mysql_store_result(mysql);
    if (res == nullptr)
    {
        std::cerr << "mysql_store_result error" << std::endl;
        return 4;
    }
​
    // 6.获取其行列信息(有多少行,多少列)
    my_ulonglong rows = mysql_num_rows(res);
    my_ulonglong fields = mysql_num_fields(res);
    std::cout << "行: " << rows << std::endl;
    std::cout << "列: " << fields << std::endl;
​
    // 7.打印列属性
    MYSQL_FIELD *fields_array = mysql_fetch_field(res);
    for (my_ulonglong i = 0; i < fields; i++)
    {
        // 该结构体中的name成员就是列名称
        std::cout << fields_array[i].name << "\t";
    }
    std::cout << std::endl;
​
    // 8.打印结果
    for (my_ulonglong i = 0; i < rows; i++)
    {
        // 获取一行的数据
        MYSQL_ROW row = mysql_fetch_row(res);
        for (my_ulonglong j = 0; j < fields; j++)
        {
            //row[j] = *(row+j)
            std::cout << row[j] << "\t";
        }
        std::cout << std::endl;
    }
​
    // 9.释放关闭工作
    // delete res;
    // 使用其对应的释放关闭接口
    mysql_free_result(res);
    mysql_close(mysql);
    return 0;
}

接着 make 编译以下,运行 ./mytest,查询结果如下:

题外话:图形化界面

其实,还可以考虑用 图形化GUI页面 来操作,这里推荐Navicat,Navicat在我学mysql之前做项目时是用过的,好像记得是要收费的,但是有学习版的(大家可以搜搜博客啥的),我这个就是学习版的,用起来其实比命令行或者api要简单容易上手很多,但是肯定就只停留在用的层面啦,理解原理还得是命令行代码~,理解之后使用图形化界面方式来操作就很舒服直观了

其界面呢就是这样的:

其实经过mysql的系统学习,使用这个图形化界面那真的就是小意思啦,各种功能都是非常清楚的!

总结:其实这个图形化界面就和我们写的c++式的客户端差不多的,只是从代码转为了鼠标图形化操作

尾声

ok,目前mysql的基础我们已经全部了解啦,目前mysql专栏的博客就要告一段落了,但是其中的很多内容我还是需要去反复复习的,大家也是需要去不断复习一下的,特别是sql语句的编写以及mysql的索引和事务相关的内容都是很重要的,这一篇的话就是说要用到的时候来查一查就基本上可以使用到代码当中了,这种api接口没有什么需要死记硬背的~

相关推荐
Omics Pro1 分钟前
中医临床决策5款大语言模型,谁主沉浮?
数据库·人工智能·机器学习·语言模型·自然语言处理·chatgpt
BomanGe102 分钟前
NSK NH35EM 高负载法兰型直线导轨详述
服务器·网络·数据库·经验分享·规格说明书
何极光5 分钟前
MySQL 8.0详细安装教程(附下载地址)
数据库·mysql·adb
2601_961875248 分钟前
花生十三资料网盘|百度云|下载
数据库·windows·git·svn·eclipse·github
承渊政道13 分钟前
【MySQL数据库学习】(MySQL复合查询)
数据库·学习·mysql·bash·database·数据库开发·数据库架构
Cx330❀17 分钟前
【MySQL基础】详解MySQL数据类型:底层原理、越界测试与最佳实践
linux·开发语言·数据库·c++·mysql
Upsy-Daisy22 分钟前
Hermes Agent 学习笔记 07:Messaging Gateway,让 Agent 从终端走向多平台入口
运维·服务器·数据库
程序员晨曦24 分钟前
数据库写轮眼:看透 MVCC 版本链、快照、隔离级别。
数据库·oracle
Leon-Ning Liu28 分钟前
MySQL数据恢复实践:binlog2sql数据追加
数据库·mysql
嵌入式-老费31 分钟前
esp32开发与应用(看门狗测试)
java·开发语言·数据库