MySQL数据库⑪_C/C++连接MySQL_发送请求

目录

1. 下载库文件

2. 使用库

3. 链接MySQL函数

4. C/C++链接示例

5. 发送SQL请求

6. 获取查询结果

本篇完。


1. 下载库文件

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

进入MySQL官网选择适合自己平台的mysql connect库,然后点击下载就行了。

比如此链接MySQL :: Download Connector/C++

下载完毕后需要将其上传到云服务器,这里将下载的库文件存放在下面的目录:

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

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

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

其中,include目录下存放的一堆头文件。而lib目录下存放的就是动静态库。


2. 使用库

为了方便在项目中使用刚才的库文件,可以在项目目录下创建两个软连接,分别连接到刚才的include目录和lib目录。

这时直接在项目目录下,就能看到刚才include和lib目录下的内容。

下面先通过调用mysql_get_client_info来判断库是否引入成功,该函数的作用就是获取客户端的版本信息。

#include <iostream>
#include <mysql.h>
using namespace std;int main()
{//获取客户端的版本信息cout<<"mysql client version: "<<mysql_get_client_info()<<endl;return 0;
}

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

  • -I(大写i):用于指明头文件的搜索路径。
  • -L:用于指明库文件的搜索路径。
  • -l(小写L):用于指明需要连接库文件路径下的哪一个库。

Makefile编写完毕后,直接通过make命令即可编译代码生成可执行程序。

但此时生成的可执行程序还不能直接运行,通过ldd命令可以看到,该可执行程序所依赖的mysqlclient库找不到。如下:

  • gcc/g++编译器默认都是动态链接的,编译代码时默认使用的是动态库,所以生成的可执行程序在运行时需要找到对应的动态库进行链接,而我们使用的mysqlclient库并不在系统的搜索路径下。
  • 需要注意的是,Makefile中的-I,-L和-l这三个选项,只是在编译期间告诉编译器头文件和库文件在哪里,而可执行程序生成后就与编译器无关了。

解决该问题通常有三种做法:

  1. 将库文件拷贝到系统默认的库文件搜索路径下/lib64。
  2. 将库文件所在的目录路径添加到LD_LIBRARY_PATH环境变量中,该环境变量可以用于指定查找动态库时的其他路径。
  3. 将库文件所在的目录路径保存到以.conf为后缀的配置文件中,然后将该文件拷贝到/etc/ld.so.conf.d/目录下,并使用ldconfig命令对配置文件进行更新,该目录下所有配置文件中的路径也将作为查找动态库时的搜索路径。

这里采用第三种方式进行解决。如下:

此时该可执行程序所依赖的mysqlclient库就能够被找到了。如下:


3. 链接MySQL函数

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

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

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

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

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_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时就会释放这个对象。

4. C/C++链接示例

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

#include <iostream>
#include <string>
#include <mysql.h>
using namespace std;const string host = "116.205.138.41";
const string user = "GR";
const string passwd = "@369rtxRTX";
const string db = "connect_demon";
const int port = 3306;int main()
{//1、创建MySQL对象MYSQL* ms = mysql_init(nullptr);//2、连接数据库if(mysql_real_connect(ms, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr){cerr<<"数据库连接失败"<<endl;return 1;}cout<<"数据库连接成功"<<endl;//3、关闭数据库mysql_close(ms);cout<<"数据库关闭成功"<<endl;return 0;
}

使用g++生成可执行程序,运行后即可看到连接数据库成功、关闭数据库成功。


5. 发送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数据库交互时,访问的都是connect_demon数据库,该数据库下有一个user表,表中有三条记录。如下:

在调用mysql_query函数时,向MySQL服务器下发一条insert SQL。如下:

#include <iostream>
#include <string>
#include <mysql.h>
using namespace std;const string host = "116.205.138.41";
const string user = "GR";
const string passwd = "@369rtxRTX";
const string db = "connect_demon";
const int port = 3306;int main()
{//1、创建MySQL对象MYSQL* ms = mysql_init(nullptr);//2、连接数据库if (mysql_real_connect(ms, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr){cerr << "数据库连接失败" << endl;return 1;}cout << "数据库连接成功" << endl;mysql_set_character_set(ms, "utf8"); //设置编码格式为utf8//3、向数据库表中插入记录std:string sql = "insert into user values (4,'赵六',25)";if (mysql_query(ms, sql.c_str()) != 0){cout << "插入数据失败" << endl;return 2;}cout << "插入数据成功" << endl;//4、关闭数据库mysql_close(ms);cout << "数据库关闭成功" << endl;return 0;
}

生成可执行程序,运行后在MySQL中即可看到对应数据被成功插入。如下:

删除和更新也和插入的做法一样。


6. 获取查询结果

  • 对数据库中的数据进行增删改操作时,都只需要调用mysql_query向服务器下发对应的SQL请求。
  • 而对数据库中的数据进行查询操作时,除了需要调用mysql_query向服务器下发对应的查询SQL,还需要获取查询结果。

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

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

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

typedef struct st_mysql_res {my_ulonglong  row_count;MYSQL_FIELD	*fields;MYSQL_DATA	*data;MYSQL_ROWS	*data_cursor;unsigned long *lengths;		/* column lengths of current row */MYSQL		*handle;		/* for unbuffered reads */const struct st_mysql_methods *methods;MYSQL_ROW	row;			/* If unbuffered read */MYSQL_ROW	current_row;		/* buffer to current row */MEM_ROOT	field_alloc;unsigned int	field_count, current_field;my_bool	eof;			/* Used by mysql_fetch_row *//* mysql_stmt_close() had to cancel this result */my_bool       unbuffered_fetch_cancelled;void *extension;
} MYSQL_RES;

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

my_ulonglong mysql_num_rows(MYSQL_RES *res);
  • 该函数将会从指定的MYSQL_RES对象中,获取查询结果的行数。

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

unsigned int mysql_num_fields(MYSQL_RES *res);
  • 该函数将会从指定的MYSQL_RES对象中,获取查询结果的列数。

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

MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES *res);
  • 该函数将会从指定的MYSQL_RES对象中,获取查询结果的列属性。

mysql_fetch_fields函数将会返回多个MYSQL_FIELD对象,每个MYSQL_FIELD对象中保存着对应列的各种列属性,其类型定义如下:

typedef struct st_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;

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

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
  • 该函数将会从指定的MYSQL_RES对象中,获取查询结果中的一行数据。

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

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

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

#include <iostream>
#include <string>
#include <mysql.h>
using namespace std;const string host = "116.205.138.41";
const string user = "GR";
const string passwd = "@369rtxRTX";
const string db = "connect_demon";
const int port = 3306;int main()
{//1、创建MySQL对象MYSQL* ms = mysql_init(nullptr);//2、连接数据库if (mysql_real_connect(ms, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr){cerr << "数据库连接失败" << endl;return 1;}cout << "数据库连接成功" << endl;mysql_set_character_set(ms, "utf8"); //设置编码格式为utf83、向数据库表中插入记录//std:string sql = "insert into user values (4,'赵六',25)";//if (mysql_query(ms, sql.c_str()) != 0)//{//    cout << "插入数据失败" << endl;//    return 2;//}//cout << "插入数据成功" << endl;//3、查询数据库表中的记录//3.1、执行查询语句std:string sql = "select * from user";if (mysql_query(ms, sql.c_str()) != 0){cout << "查询数据失败" << endl;return 2;}cout << "查询数据成功" << endl;//3.2、获取查询结果MYSQL_RES* res = mysql_store_result(ms);int rows = mysql_num_rows(res); //数据的行数int cols = mysql_num_fields(res); //数据的列数//获取每列的属性并打印列名MYSQL_FIELD* fields = mysql_fetch_fields(res);for (int i = 0;i < cols;i++){cout << fields[i].name << "\t";}cout << endl;for (int i = 0;i < rows;i++){//获取一行数据并进行打印MYSQL_ROW row = mysql_fetch_row(res);for (int j = 0;j < cols;j++){cout << row[j] << "\t";}cout << endl;}free(res); //释放内存空间//4、关闭数据库mysql_close(ms);cout << "数据库关闭成功" << endl;return 0;
}

生成可执行程序,运行后在即可看到数据的查询结果。如下:


本篇完。

此专栏到这就先告一段落了。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/259104.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Codeforces Round 926 (Div. 2) C. Sasha and the Casino (Java)

Codeforces Round 926 (Div. 2) CC. Sasha and the Casino (Java) 比赛链接&#xff1a;Codeforces Round 926 (Div. 2) C题传送门&#xff1a;C. Sasha and the Casino 题目&#xff1a;C. Sasha and the Casino **Example ** input 2 1 7 2 1 1 2 3 15 3 3 6 4 4 5 5 4 7…

云计算基础-计算虚拟化-CPU虚拟化

CPU指令系统 在CPU的工作原理中&#xff0c;CPU有不同的指令集&#xff0c;如下图&#xff0c;CPU有4各指令集&#xff1a;Ring0-3&#xff0c;指令集是在服务器上运行的所有命令&#xff0c;最终都会在CPU上执行&#xff0c;但是CPU并不是说所有的命令都是一视同仁的&#xf…

【java】Hibernate访问数据库

一、Hibernate访问数据库案例 Hibernate 是一个在 Java 社区广泛使用的对象关系映射&#xff08;ORM&#xff09;工具。它简化了 Java 应用程序中数据库操作的复杂性&#xff0c;并提供了一个框架&#xff0c;用于将对象模型数据映射到传统的关系型数据库。下面是一个简单的使…

uniapp API文档地址 以及 HBuilder安装

uniapp API文档地址 以及 HBuilder安装 一、进入 当前网站 uni-app 官网 二、点击截图下载文件 三、下载HBuilder X 进入 当前网站 浏览器会识别 也可以自行选择版本四、直接点击Download For Windows 直接点击下载会下载压缩包 解压 后 双击截图内的 .exe五、以上上述完…

C++初阶:容器适配器介绍、stack和queue常用接口详解及模拟实现

介绍完了list类的相关内容后&#xff1a;C初阶&#xff1a;适合新手的手撕list&#xff08;模拟实现list&#xff09; 接下来进入新的篇章&#xff0c;stack和queue的介绍以及模拟&#xff1a; 文章目录 1.stack的初步介绍2.stack的使用3.queue的初步介绍4.queue的使用5.容器适…

Python六级考试笔记

Python六级考试笔记【源源老师】 六级标准 一、 掌握文件操作及数据格式化。 二、 掌握数据可视化操作。 三、 理解类与对象的概念&#xff0c;初步掌握类与对象的使用。 四、 掌握SQLite数据库基础编程。 五、 掌握简单的使用tkinter的GUI设计。 ​ 1. 文件操作 &#xff0…

每日OJ题_二叉树dfs①_力扣2331. 计算布尔二叉树的值

目录 力扣2331. 计算布尔二叉树的值 解析代码 力扣2331. 计算布尔二叉树的值 2331. 计算布尔二叉树的值 难度 简单 给你一棵 完整二叉树 的根&#xff0c;这棵树有以下特征&#xff1a; 叶子节点 要么值为 0 要么值为 1 &#xff0c;其中 0 表示 False &#xff0c;1 表示…

【C++】模版初阶

目录 泛函编程 函数模版 概念 格式 原理 实例化 模版函数的匹配原则 类模板 定义格式 泛函编程 如何实现一个通用的交换函数呢&#xff1f; void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& left, dou…

数学建模:K-means聚类手肘法确定k值(含python实现)

原理 当K-means聚类的k值不被指定时&#xff0c;可以通过手肘法来估计聚类数量。   在聚类的过程中&#xff0c;随着聚类数的增大&#xff0c;样本划分会变得更加精细&#xff0c;每个类别的聚合程度更高&#xff0c;那么误差平方和&#xff08;SSE&#xff09;会逐渐变小&am…

上门回收小程序开发,互联网下发展机遇

在当下生活水平大幅度上升发展下&#xff0c;回收成为了人们日常生活中的一部分。 如今&#xff0c;随着互联网的快速发展&#xff0c;回收行业也进行了升级换代&#xff0c;由传统的线下回收门店到回收箱在到当下的线上互联网回收模式&#xff0c;迈向了“互联网废品回收”的…

如何清除谷歌浏览器的缓存?这里有详细步骤

如果你想解决加载或格式化问题&#xff0c;以改善你在谷歌Chrome上的浏览体验&#xff0c;那么清除缓存和cookie是一个很好的开始。以下是删除它们的方式和操作。 删除缓存和cookie时会发生什么 当你访问一个网站时&#xff0c;它有时会保存&#xff08;或记住&#xff09;某…

使用 Chainlit, Langchain 及 Elasticsearch 轻松实现对 PDF 文件的查询

在我之前的文章 “Elasticsearch&#xff1a;与多个 PDF 聊天 | LangChain Python 应用教程&#xff08;免费 LLMs 和嵌入&#xff09;” 里&#xff0c;我详述如何使用 Streamlit&#xff0c;Langchain, Elasticsearch 及 OpenAI 来针对 PDF 进行聊天。在今天的文章中&#xf…

002 GIS数据的基本格式

1 地理空间信息 地理空间信息的数据模型是现实世界的特征组到理想状态的简化或抽象&#xff0c; 并且可以在各种GIS软件的用户使用层&#xff08;结构化&#xff09;模型有很多。 该层模型由多个空间数据的分层构建&#xff0c;如 图 1.5 。 根据内容&#xff0c;离散特征信息…

React环境配置

1.安装Node.js Node.js官网&#xff1a;https://nodejs.org/en/ 下载之后按默认选项安装好 重启电脑即可自动完成配置 2.安装React 国内使用 npm 速度很慢&#xff0c;可以使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm。 ①使用 winR 输入 cmd 打开终端 ②依…

怎样让MCU/SFU视频会议ovmedia 接入GB28281监控视频参会互动

在国内视频应用对GB监控接入是常规操作&#xff0c;很多系统需要接入监控视频交互处理。我们以ovmedia视频会议为例做一个接入互动。 GB28181协议在流媒体系统较为普及&#xff0c;我们以开源SRS系统对接监控端再接入会议&#xff08;也可以用商用GB流平台&#xff0c;操作基本…

VNCTF 2024 Web方向 WP

Checkin 题目描述&#xff1a;Welcome to VNCTF 2024~ long time no see. 开题&#xff0c;是前端小游戏 源码里面发现一个16进制编码字符串 解码后是flag CutePath 题目描述&#xff1a;源自一次现实渗透 开题 当前页面没啥好看的&#xff0c;先爆破密码登录试试。爆破无果…

MATLAB知识点:uniquetol函数(★★☆☆☆)考虑了一定的容差的unique函数

讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自第3章&#xff1a;课后习题讲解中拓展的函数 在讲解第三…

wayland(xdg_wm_base) + egl + opengles——dma_buf 作为纹理数据源(五)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、EGL dma_buf import 相关的数据结构和函数1. EGLImageKHR2. eglCreateImageKHR()3. glEGLImageTargetTexture2DOES()二、egl 中 import dma_buf 作为纹理的代码实例1. egl_wayland_dmabuf_…

洛谷: P1479 宿舍里的故事之五子棋

题目链接: https://www.luogu.com.cn/problem/P1479 思路: 这道题目可以打表或者搜索。每个位置有选择/不选择两种情况。搜索的时候我们一行一行的搜索&#xff0c;直到使用的棋子达到n为止。b[i]为五子连线的数量&#xff0c;b[i] 1表示五子连线的数量可以取i&#xff0c;在…

圆筒形正压式采样器

一个人不愿意努力的时候&#xff0c;你怎样帮他也没有用&#xff01;一个人不愿意被点燃的时候&#xff0c;你怎样燃烧也没有用&#xff01;自己想醒&#xff0c;没有闹铃也能够醒来&#xff01;自己想努力&#xff0c;没有帮助也能够成功&#xff01;自己想点燃梦想&#xff0…