【MySQL】深度学习数据库开发技术:使用CC++语言访问数据库
**前言:**本节内容介绍使用C/C++访问数据库, 包括对数据库的增删查改操作。 主要是学习一些接口的调用, 废话不多说, 开始我们的学习吧!
ps:本节内容比较容易, 友友们放心观看哦!
目录
准备mysql库
使用mysql库?
编译文件
官方API文档
对象的创建和关闭
链接数据库
下达sql指令
select语句
准备mysql库
其实我们访问mysql不只是使用命令行进行访问, 我们未来访问数据库一定是一个程序对数据库进行访问, 而程序其实就是代码。所以未来我们可以使用代码来访问数据库, 这里我们使用C/C++代码对数据库进行访问。
首先我们创建一个非root级别用户和一个数据库:
然后我们要知道, 我们访问数据要有对应的开发包, 这些开发包我们可以直接在apt里面找到下载安装。
sudo apt install -y libmysqlclient-dev
安装好了之后我们就能在/usr/include/路径下面看到mysql目录
这个 里面包含着我们需要的文件, 像什么mysql.h就是我们所需要的。
然后在/usr/lib/x86_64-linux-gnu里面也有我们的mysql的连接库:

使用mysql库
编译文件
然后使用库,系统会默认搜索的路径是/lib/include路径, 然后我们要使用的mysql.h头文件在/lib/include西面的/mysql目录下面, 所以我们包含头文件要使用mysql/mysql.h:
#include<mysql/mysql.h>
mysql_get_client_info函数可以打印当前mysql的版本信息。
#include<iostream>
#include<mysql/mysql.h>
using namespace std;int main()
{cout << "mysql_client version: " << mysql_get_client_info() << endl; return 0;
}
然后编译可能会出现问题:

这是因为因为我们编译的时候系统找不到链接的库, 所以需要我们使用-l指令指定路径:
-lmysqlclient;
然后就能运行成功了:
官方API文档
然后就是我们要对数据库进行增删查改,我们可以去mysql的官方文档进行查看对应的资料
先进入官方网站,点击文档:

然后下滑找到并点击C API:
然后点击function就能看到我们常用的一些函数了:
知道了这些之后, 下面开始学习增删查改:
对象的创建和关闭
#include<iostream>
#include<mysql/mysql.h>
using namespace std;int main()
{MYSQL* my = mysql_init(nullptr);if (nullptr){cerr << "init MySQL error" << endl;return 1;}mysql_close(my);return 0;
}
这里面的MYSQL类型就类似于我们C语言里面的FILE类型, 都是一个句柄。如果成功了就是返回一个非空的值, 就代表我们获得了拒柄。
既然获得句柄, 那么最后情况下还要关闭数据库, 释放一系列资源。 使用mysql_close函数, 就类似于我们关闭文件的操作。
链接数据库
在官方文档中给出的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 client_flag)
其中的第一个参数就是我们刚刚获取的句柄。 然后第二个参数就是登录的mysql所在的ip地址, 这里我们采用本地环回;第三个参数就是就是使用的用户名;第四个参数就是对应用户的密码;第五个参数就是数据库的名称;第六个参数就是端口号;剩下的参数默认即可。返回值就是MYSQL*也就是句柄, 如果是nullptr就是连接失败。
#include<iostream>
#include<mysql/mysql.h>
#include<string>
using namespace std;
const string host = "localhost";
const string user = "mian_yang";
const string passwd = "XXXXXXXXXXXXXXXX";
const string db = "school_book_manage";
const unsigned int port = 3306;int main()
{MYSQL* my = mysql_init(nullptr);if (nullptr){cerr << "init MySQL error" << endl;return 1;}//if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr){cerr << "connect error" << endl;return 0;}//cout << "connect success" << endl;mysql_close(my);return 0;
}
然后我们编译一下运行一下:
下达sql指令
然后我们就可以使用函数下达sql指令, 在官方文档中给出的函数如下:
int
mysql_query(MYSQL *mysql,const char *stmt_str)
其中第一个参数就是我们的句柄。 然后第二个参数就是我们要下达的指令。返回值如果为零就执行成功了, 如果不为零, 就执行失败了。然后下面是代码:
#include<iostream>
#include<mysql/mysql.h>
#include<string>
using namespace std;
const string host = "localhost";
const string user = "mian_yang";
const string passwd = "MYhylk563_al36huz.6";
const string db = "school_book_manage";
const unsigned int port = 3306;int main()
{MYSQL* my = mysql_init(nullptr);if (nullptr){cerr << "init MySQL error" << endl;return 1;}//if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr){cerr << "connect error" << endl;return 0;}//cout << "connect success" << endl;string sql;while (true){cout << ">>";if (!getline(cin, sql) || sql == "quit") break;int n = mysql_query(my, sql.c_str());if (n == 0) {cout << sql << " success "<<endl;}else cout << sql << " error" << endl;}mysql_close(my);return 0;
}
运行的时候我们就来测验一下进行插入:
然后也可以看到我们的sql语句执行成功了!
现在我们插入一下李四, 插入中文, 我们查看一下结果:


我们会看到李四被正常的插入进去了。 这里博主要说的是, 对于mysql8.0来说, 博主使用的是mysql8.0, 这里使用插入函数插入中文会正常插入。 但是如果是5.7版本的mysql, 那么这里如果插入中文插入的就是一堆乱码。所有的乱码问题都是客户端和服务器双方没有形成编码一致。比如说服务端使用utf8, 而客户端使用的是其他的编码方式。编码不一致,那么我编码使用的是utf8, 你解码使用的是其他的方式。 那么就乱码了。
这里我们的8.0数据库, 表编码都是utf8mb4的,说明我们的客户端也是utf8mb4的。如果我们设置成其他的再插入就是一堆乱码, 这里试验一下:使用mysql_set_character_set函数设置解码方式:
mysql_set_character_set(my, "latin1");

插入成功:


可以看到, 解码出来就是一堆乱码。
现在问题来了, 我们上面的插入试验成功了, select语句呢? 我们的select语句是查, 要打印给我们一系列信息。 这里博主可以说一下实验结果, 结果是执行成功, 但是没有打印结果。 其他的像update, delete操作都能执行成功。 只有select 虽然执行成功但是没有给我们显示信息, 这是因为其他的sql语句都只需要执行成功即可, 但是select语句还要进行后续的处理, 比如打印。 所以select语句怎么处理呢?
select语句
我们查出来的是一种表结构。 如果我们查出来有四条数据, 那么就有四行。 如果我们查出来的表有四列属性, 那么查出来就有四列。 我们要知道我们要查的是一些数据。 那么这些数据在mysql内部就一定要有对应的内存空间保存这个数据。 mysql将所有的数据读取出来的时候全部都当作字符串了。 然后有一个MYSQL_RES对象,MYSQL_RES对象就是将这些数据进行整合一下。 我们可以把MYSQL_RES对象看成一个数组的指针, 这个数组里面存储的数据类型是char**类型。 数组的大小表示一共有多少条记录。

然后这些元素都指向一个char*的数组:

这个char*元素指向的就是我们的表结构里面的属性元素。 所以未来我们就可以把MYSQL_RES堪称一个char** XXX[]数组。
所以, 这个MYSQL_RES其实就是我们使用select语句之后返回的结果, 这个结果的集合就在MYSQL_RES对象中。 未来我们想要去除其中的对象, 我们需要先获取这个结果集里面的行, 里面的列:
MYSQL_RES *
mysql_store_result(MYSQL *mysql); //获得结果集
uint64_t
mysql_num_rows(MYSQL_RES *result); //获取行
unsigned int
mysql_num_fields(MYSQL_RES *result); //获取列
为了更好的遍历, mysql提供了一种数据结构MYSQL_ROW, 方便我们更好的遍历, 以后我们就可以直接把这个RES结果集当成一个二维数组来使用。这个MYSQL_ROW就相当于迭代器, 我们每次调用, 它都可以自动加。
MYSQL_ROW
mysql_fetch_row(MYSQL_RES *result);
然后我们不仅有数据, 还有我们的列名(列属性)所以我们就可以获取一下列名:
MYSQL_FIELD *
mysql_fetch_fields(MYSQL_RES *result)
这个函数的返回值是一个结构里, 这个结构体里面有着列名称、取别名后的原生列名称、 属于哪个表、属于哪个数据库等等:
未来我们想要的就是这个name字段。 我们然后就可以向遍历数组一样遍历这个列属性,打印出来列属性。
所以, 下面为全部的代码:
#include<iostream>
#include<mysql/mysql.h>
#include<string>
using namespace std;
const string host = "localhost";
const string user = "mian_yang";
const string passwd = "MYhylk563_al36huz.6";
const string db = "school_book_manage";
const unsigned int port = 3306;int main()
{MYSQL* my = mysql_init(nullptr);if (nullptr){cerr << "init MySQL error" << endl;return 1;}//if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr){cerr << "connect error" << endl;return 0;}//cout << "connect success" << endl;string sql = "select * from user";int n = mysql_query(my, sql.c_str());if (n == 0) cout << sql << " success" << endl;else {cerr << sql << " error" << endl;return 3;}//MYSQL_RES* res = mysql_store_result(my);if (res == nullptr) {cerr << "res error" << endl;return 4;}MYSQL_FIELD* fields = mysql_fetch_fields(res);my_ulonglong cols = mysql_num_rows(res);for (int i = 0; i < cols; i++){cout << fields[i].name << " ";}cout << endl; my_ulonglong rows = mysql_num_rows(res);for (int i = 0; i < rows; i++){MYSQL_ROW row = mysql_fetch_row(res);for (int j = 0; j < cols; j++){cout << row[j] << " ";}cout << endl;}mysql_close(my);return 0;
}
然后打印就打印出来了:
对于MYSQL_RES, 其实MYSQL_RES就是在内存中申请了一大块内存空间, 所以最后我们还要free这块空间。而上层用户如果使用free释放空间就会造成内存泄漏或者使用内部的原生指针太麻烦。 所以就提供了一个接口:
void
mysql_free_result(MYSQL_RES *result)
这个函数就是系统提供的释放我们的结果集。
--------------------------------------------------------------------------------------------------------------------------------

——————以上就是本节全部内容哦, 如果对友友们有帮助的话可以关注博主, 方便学习更多知识哦!!!
相关文章:
【MySQL】深度学习数据库开发技术:使用CC++语言访问数据库
**前言:**本节内容介绍使用C/C访问数据库, 包括对数据库的增删查改操作。 主要是学习一些接口的调用, 废话不多说, 开始我们的学习吧! ps:本节内容比较容易, 友友们放心观看哦! 目录 准备mysql…...
LabVIEW化工实验室设备故障实时监测
化工实验室中,各类设备的运行状态直接影响实验的精度与安全性。特别是重要分析仪器的突发故障,可能导致实验中断或数据失效。为了实现设备运行状态的实时监控与故障快速响应,本文提出了一套基于LabVIEW的解决方案,通过多参数采集、…...
单例模式懒汉式、饿汉式(线程安全)
饿汉式单线程安全吗 饿汉式单例(Eager Singleton)是线程安全的。这种实现方式在类加载时就创建了单例实例,因此在多线程环境中,不存在多个线程同时创建实例的问题。 饿汉式单例的实现 以下是一个饿汉式单例的示例: …...
Cursor登录按钮点击没反应
问题 系统:Windows11 Cursor:Cursor 0.44.9 当安装Cursor打开进行登录时,点击Sign in没反应 解决方案 1.打开window11的设置 2.点击应用中的默认应用 3.在设置应用程序的默认值中搜索Google(没有Google浏览器的尝试下载一个&a…...
论文实现:Reactive Nonholonomic Trajectory Generation via Parametric Optimal Control
1. 多项式螺旋 曲率: κ ( s ) a 0 a 1 s a 2 s 2 a 3 s 3 a 4 s 4 a 5 s 5 \begin{align} \kappa(s) a_0 a_1s a_2s^2 a_3s^3 a_4s^4 a_5s^5 \end{align} κ(s)a0a1sa2s2a3s3a4s4a5s5 机器人朝向: θ ( s ) a 0 s a 1 …...
基于单片机中药存放环境监测系统的实现
基于单片机中药存放环境监测系统的实现 项目开发背景 随着现代中药的广泛应用,中药材的存储环境对其质量有着至关重要的影响。温湿度、烟雾、火灾等环境因素,若不加以控制,将会导致中药材失效或变质。因此,设计一个基于单片机的…...
九垠赢+商业管理系统 Common.ashx 文件上传致RCE漏洞复现
0x01 产品简介 九垠赢+商业管理系统是基于互联网技术的进销存管理软件,适用于新零售背景下各种业态的线上线下一体化的商超经营管理。赢+ERP以商业管理系统为底座,融合了多种软、硬件解决方案,实现了从企业、供应商、三方平台到顾客等日常管理的全线数字化、智能化和移动化…...
速盾:服务器CDN加速解析的好处有哪些呢?
随着互联网应用的普及,越来越多的企业开始关注如何提升网站的访问速度和用户体验。为了实现这一目标,许多企业选择使用CDN(内容分发网络)来加速网站的内容分发。CDN通过在全球范围内分布多个节点,将内容缓存到离用户最…...
C++ 设计模式:备忘录模式(Memento Pattern)
链接:C 设计模式 链接:C 设计模式 - 状态模式 备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装性的前提下捕获和恢复对象的内部状态。这个模式在需要保存和恢复对象状态的场景中非常有用ÿ…...
Android 系统 Activity 系统层深度定制的方法、常见问题以及解决办法
Android 系统 Activity 系统层深度定制的方法、常见问题以及解决办法 目录 引言Activity 系统层概述Activity 系统架构图Activity 系统层深度定制的方法 4.1 自定义 Activity 生命周期4.2 自定义 Activity 启动流程4.3 自定义 Activity 转场动画4.4 自定义 Activity 窗口管理4…...
PDF怎么压缩得又小又清晰?5种PDF压缩方法
PDF 文件在日常办公与学习中使用极为频繁,可想要把它压缩得又小又清晰却困难重重。一方面,PDF 格式本身具有高度兼容性,集成了文字、图像、矢量图等多样元素,压缩时难以兼顾不同元素特性,稍不注意,文字就会…...
YK人工智能(三)——万字长文学会torch深度学习
2.1 张量 本节主要内容: 张量的简介PyTorch如何创建张量PyTorch中张量的操作PyTorch中张量的广播机制 2.1.1 简介 几何代数中定义的张量是基于向量和矩阵的推广,比如我们可以将标量视为零阶张量,矢量可以视为一阶张量,矩阵就是…...
关于CISP报名费用详情
CISP即“注册信息安全专业人员”,是中国信息安全测评中心实施的国家认证项目,旨在培养信息安全领域的专业人才。对于有意报考CISP的考生而言,了解报名考试费用是备考过程中不可或缺的一环。 CISP的报名考试费用主要包括培训费用、考试费用、…...
vim 按下esc后取消高亮
配置 ideavimrc文件 " 按下 Esc 键时自动取消高亮 " 在普通模式下按下 Esc 键取消高亮 nnoremap <Esc> :nohlsearch<CR> " 在插入模式下按下 Esc 键取消高亮 inoremap <Esc> <Esc>:nohlsearch<CR>" 额外:当退出…...
SwiftUI:多语言实现富文本插值
实现的UI需求: 要求: 英文显示:3068 people have joined this plan today! 中文显示:今日有 3068 人已加入此计划! 实现代码: Text(AttributedString(localized:"**\(payPeoples)** people have joi…...
操作系统基础
概念 控制和管理操作系统软件和硬件 用户观点:用户和计算机之间的接口 基本概念 特征 并发,共享,虚拟,异步 功能 处理机管理,存储器管理,文件管理,设备管理 作为用户和硬件接口 命令接口&am…...
函数调用流程可用工具
方法 1、gdb,这个网上很多找找就有 2、tcmalloc,直接在调用的地方调一个malloc就可以看到调用的流程,具体见tcmalloc 3、backtrace,个人感觉这么最方便,具体见backtrace...
UniApp 页面布局基础
一、UniApp 页面布局简介 在当今的移动应用开发领域,跨平台开发已成为一种主流趋势。UniApp作为一款极具影响力的跨平台开发框架,凭借其“一套代码,多端运行”的特性,为开发者们提供了极大的便利,显著提升了开发效率。…...
2D图像测量到3D点云之物体三维尺寸测量!!!!
0,引言 本文将从双目采集的2D图像到3D点云进行转化,并进行物体尺寸测量,旨在为读者展示2D图像如何关联3D点云,并进行相关工业应用。 将2D图像转化为3D点云,并进行物体尺寸测量的技术,在工业领域有着广泛的…...
[TOTP]android kotlin实现 totp身份验证器 类似Google身份验证器
背景:自己或者公司用一些谷歌身份验证器或者microsoft身份验证器,下载来源不明,或者有广告,使用不安全。于是自己写一个,安全放心使用。 代码已开源:shixiaotian/sxt-android-totp: android totp authenti…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...
RLHF vs RLVR:对齐学习中的两种强化方式详解
在语言模型对齐(alignment)中,强化学习(RL)是一种重要的策略。而其中两种典型形式——RLHF(Reinforcement Learning with Human Feedback) 与 RLVR(Reinforcement Learning with Ver…...
JVM——对象模型:JVM对象的内部机制和存在方式是怎样的?
引入 在Java的编程宇宙中,“Everything is object”是最核心的哲学纲领。当我们写下new Book()这样简单的代码时,JVM正在幕后构建一个复杂而精妙的“数据实体”——对象。这个看似普通的对象,实则是JVM内存管理、类型系统和多态机制的基石。…...
【电路笔记】-变压器电压调节
变压器电压调节 文章目录 变压器电压调节1、概述2、变压器电压调节3、变压器电压调节示例14、变压器电压调节示例25、变压器电压调节示例36、总结变压器电压调节是变压器输出端电压因连接负载电流的变化而从其空载值向上或向下变化的比率或百分比值。 1、概述 电压调节是衡量变…...



