【MySQL】Linux下用C/C++链接MySQL数据库
文章目录
- 一、准备工作
 - 二、验证库和接口的使用
 - 三、链接数据库
 - 四、对数据库进行增删查改
 - 增
 - 删
 - 改
 - 查
 
- 五、结尾
 
一、准备工作
要使用C++链接数据库, 首先要去MySQL官网下载官网提供的库, MySQL 社区下载.
 如图所示:
 
 接着选择:
 
 按需选择版本:
 
 如果用的是云服务器, 那么在安装mysql时默认就会把这些库都给装上了.
成功安装后会获得这些库和接口:
 查看头文件指令:
ls /usr/include/mysql/
 

 查看库的指令:
ls /lib64/mysql/
 

 如果查看对应目录存在这些库和接口就ok了.
二、验证库和接口的使用
需要包含的头文件: #include <mysql/mysql.h>
 测试代码:
#include <mysql/mysql.h>
#include <iostream>
using namespace std;int main()
{cout << "mysql client version: " << mysql_get_client_info() << endl;return 0;
}
 
函数: mysql_get_client_info()
 这个函数的功能就是查看当前mysql客户端的版本, 如果能成功执行并输出版本号, 就表示当前库和接口都是可以使用的, 可以开始链接数据库了.
 一般来说直接编译会失败, 会出现类似提示:
 
 要解决该问题, 首先在编译时指明头文件所在目录, 库所在目录, 再指定需要链接的库的名字, 如下:
g++ -o test test.cpp -std=c++11 -I /usr/include/mysql -L /lib64/mysql -lmysqlclient
 
再把库所在的路径添加到系统的动态库查找路径中:
export LD_LIBRARY_PATH=./lib64
 
此时直接执行就好了, 结果如下:
 
 成功输出版本信息就对了.
三、链接数据库
- 首先需要定义一个类型为MYSQL*的变量, 并使用
MYSQL *mysql_init(MYSQL *mysql)函数对该变量进行初始化 
MYSQL* my = mysql_init(nullptr); //定义并初始化MySQL变量
 
- 初始化完毕后, 进行链接数据库操作, 通过函数:
 
MYSQL* mysql_real_connect(MYSQL *mysql, //调用mysql_init()以初始化MYSQL结构变量const char *host, //主机名或 IP 地址const char *user, //用户的 MySQL 登录 IDconst char *passwd, //密码, 如果passwd为NULL,则仅检查表中user具有空白密码字段的用户条目是否匹配。const char *db, //数据库名称unsigned int port, //端口号const char *unix_socket, //如果unix_socket不是 NULL,则字符串指定要使用的套接字或命名管道unsigned long client_flag //client_flag通常为0,但可以设置为其他标志的组合以启用某些功能)
 
示例代码:
mysql_real_connect(my, "127.0.0.1", "root", nullptr, "conn", 3306, nullptr, 0)
 
关于mysql_real_connect()的返回值:
 
 可以根据返回结果判断是否真的链接上数据库, 具体代码:
#include <mysql/mysql.h>
#include <iostream>
using namespace std;int main()
{MYSQL* my = mysql_init(nullptr); //定义并初始化MySQL变量//链接数据库if(mysql_real_connect(my, "127.0.0.1", "root", nullptr, "conn", 3306, nullptr, 0)){cout << "connect success." << endl;}return 0;
}
 
结果:
 
四、对数据库进行增删查改
向链接的数据库下发sql语句的函数int mysql_query(MYSQL *mysql, const char *stmt_str).
 第一个参数是之前初始化的MYSQL*变量, 第二个参数是字符串形式的sql语句.
 返回值:
 
增删查改操作的表结构:
 
增
首先看到表里是没有数据的:
 
 通过mysql_query()插入数据:
mysql_query(my, "insert info(name,age,gender) values('张三',18,1)");
 
执行后, 数据成功插入对应的数据库中:
 
 其他的数据都和预期插入的数据一致, 唯独name不一致, 这是因为我的数据库的字符集是utf8而通过语言设置链接的默认字符集为latin1, 由于字符集不匹配而导致了乱码, 所以在建立链接后可以修改默认字符集:
mysql_set_character_set(my, "utf8"); //设置字符集
 
再编译执行:
 
 此次插入的数据就没问题了.
删
通过
mysql_query(my, "delete from info;");
 
直接执行, 结果:
 
 成功删除.
改
现在表中没有数据, 先插入一条数据:
mysql_query(my, "insert info values(1,'张三',18,1)");
 
查看表中的数据:
 
 接着输入更新的sql语句就完事了:
mysql_query(my, "update info set age=28 where id=1");
 
将年龄更改为28, 编译执行后:
 
查
增删改都很简单, 就是在mysql_query()中写sql语句, 然后查看操作是否成功就好了, 但是查的话不太一样, 虽然查询语句也是直接在mysql_query()中写, 但是查的关键是要拿到查询结果, 需要获得查询结果可以通过函数:
MYSQL_RES* mysql_store_result(MYSQL *mysql)
 
参数就是之前定义的那个MYSQL类型的变量, 而返回值是重点:
 
 也就是要定义一个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_query(my, "select * from info"); //查询MYSQL_RES* res = mysql_store_result(my); //获取结果结构体
int row = mysql_num_rows(res); //获取行数
int col = mysql_num_fields(res); //获取列数
MYSQL_FIELD* fields = mysql_fetch_fields(res); //获得属性名称for(int i = 0; i < col; ++i)
{cout << fields[i].name << " ";
}
cout << endl;
 
输出结果:
 
 没问题, 成功拿到属性名称, 接着来获取数据内容, 通过函数MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)可以获取到, 其返回值为MYSQL_ROW类型的一个变量, 可以把它当成一个char**的二维数组来使用, 类似:
 
 例子:
MYSQL_ROW line;
for(int i = 0; i < row; ++i)
{line = mysql_fetch_row(res);for(int j = 0; j < col; ++j){cout << line[j] << '\t';}cout << endl;
}
 
输出结果:
 
 没问题, 成功获取到了表中的内容数据, 需要注意想要获取下一行数据内容并不需要我们手动操作, 每调用一次mysql_fetch_row(res)函数都会自动获取下一行的内容数据, 然后再遍历该行的内容数据即可, 完整获取查询结果代码:
mysql_query(my, "select * from info");MYSQL_RES* res = mysql_store_result(my); //获取结果结构体
int row = mysql_num_rows(res); //获取行数
int col = mysql_num_fields(res); //获取列数
MYSQL_FIELD* fields = mysql_fetch_fields(res); //获得属性名称//获取属性名称
for(int i = 0; i < col; ++i)
{cout << fields[i].name << '\t';
}
cout << endl;MYSQL_ROW line;
//获取内容数据
for(int i = 0; i < row; ++i)
{line = mysql_fetch_row(res);for(int j = 0; j < col; ++j){cout << line[j] << '\t';}cout << endl;
}
 
结果:
 
五、结尾
在最后不需要访问数据库了, 记得把链接关了, 通过函数void mysql_close(MYSQL *mysql)来关闭链接, 参数即为之前创建的MYSQL*类型的变量.
 如需了解其他接口, 可直接访问MySQL的官方文档: C API 函数参考
相关文章:
【MySQL】Linux下用C/C++链接MySQL数据库
文章目录 一、准备工作二、验证库和接口的使用三、链接数据库四、对数据库进行增删查改增删改查 五、结尾 一、准备工作 要使用C链接数据库, 首先要去MySQL官网下载官网提供的库, MySQL 社区下载. 如图所示: 接着选择: 按需选择版本: 如果用的是云服务器, 那么在安装mysql时…...
Python金融量化专栏简介
量化分析实战 - 专栏大纲 👉👉👉 《玩转Python金融量化专栏》👈👈👈 订阅本专栏的可以下载对应的代码和数据集 专栏目标 本专栏旨在帮助读者全面掌握使用Python进行金融技术指标的计算与应用,从基础到高级,涵盖各种技术指标的实现、策略开发与回测等内容。通过…...
出行365:依托分布式数据库,让出行无忧 | OceanBase案例
*本文首发自“新华社环球”杂志,作者张海鑫 每年的暑期旅游旺季,都会触发一轮轮的文旅消费的热潮,对于互联网出行服务行业而言,这既是一场盛大的狂欢,也是对其综合实力的严峻考验。 然而,自去年暑假起&…...
【C语言】位段详解
🦄个人主页:小米里的大麦-CSDN博客 🎏所属专栏:https://blog.csdn.net/huangcancan666/category_12718530.html 🎁代码托管:黄灿灿 (huang-cancan-xbc) - Gitee.com ⚙️操作环境:Visual Studio 2022 目录 一、什么是位段? 二、…...
LVS集群实验
NAT模式 本质是多目标IP的DNAT,通过将请求报文中的目标地址和目标端口修改为某挑出的RS的RIP和PORT实现转发RIP和DIP应在同一个IP网络,且应使用私网地址:RS的网关要指向DIP请求报文和响应报文都必须经由Direclor转发,Direclor易于成为系统瓶…...
在 Spring Boot 中使用适配器模式实现支付网关的统一接口
引言 在许多电子商务系统中,集成多个支付网关是常见的需求。不同的支付网关有着不同的接口和实现细节。适配器模式可以帮助我们以一种灵活的方式实现这些不同的支付网关接口。 适配器模式简介 适配器模式将一个类的接口转换为客户期望的另一个接口。适配器模式使…...
【书生·浦语大模型实战营】第三期 入门岛作业
入门岛作业 Linux闯关任务:完成 SSH 连接与端口映射并运行 hello_world.py。配置vscode作业内容 可选任务1:将Linux基础命令在开发机上完成一遍作业内容 可选任务 2:使用 VSCODE 远程连接开发机并创建一个conda环境作业内容 可选任务 3&#…...
Redis的String类型常用命令总结
1. set 设置一个键的值。 set key value示例: set username "alice"2. get 获取一个键的值。 get key示例: get username3. getset 设置键的值,并返回键的旧值。 getset key value示例: getset username "…...
河南萌新联赛2024第(四)场:河南理工大学
A 思路: B 思路:有一种贪心的写法,将整个数组排序以后比较两个相邻数的同或值,取 m a x max max,不会证明 int th(int x, int y, int z) {int res 0;for (int i z - 1; i > 0; i --) {int dx (x >> i &…...
Linux中临时使用账号提权进行业务操作
普通账号提权 su:永久提权 Switching users with su sudo:临时提权 Running commands as root with sudo 1)su切换账号 需要对方的密码 示例:切换到超级管理员 su - root 建议用-这个 su root 普通用户需要执行特殊指令&…...
lwip 3. 网线拔掉后 lwip_recvfrom不能返回
当网线被拔掉后,LWIP的lwip_recvfrom函数无法返回,这通常意味着网络连接已经断开,而LWIP没有自动检测到这种断开并进行相应的处理。具体卡在这个地方: ret xQueueReceive(mbox->mbx, &(*msg), portMAX_DELAY); //具…...
Linux环境安装Docker Engine
Docker是一个开源的应用容器引擎,由Go语言开发,基于Linux内核技术。Docker通过将应用及其依赖打包到可移植的容器中,实现了应用的快速部署和高效管理。Docker容器具有轻量级、快速启动、可移植性强等特点,能够显著提升资源利用率和…...
大厂面试题分享
大厂面试题分享 Redis持久化方式AOF优缺点RDB优缺点 如何保证Redis和Myql的一致性索引下推输入url到浏览器发生了什么ReentranLock底层原理SpringBoot 的启动流程 Redis持久化方式 Redis提供了两种主要的持久化机制,分别是AOF(Append-Only File…...
FPGA面试问题整理
1. 逻辑设计中竞争与冒险概念,如何识别和消除? 竞争:在组合逻辑电路中,信号经过多条路径到达输出端,每条路径经过的逻辑门不同存在时差,在信号变化的瞬间存在先后顺序。这种现象叫竞争。 冒险:由…...
3Done学习笔记
一、基本操作 1、旋转视角 使用左下角立方体选择; 右键可以拖动视角; 中间滑轮按住拖动整个舞台界面。 2、平移和旋转 右键选择移动,有两种方式。 第一种选择起始点,按照起始点位置移动到终止点(边、角、中心点…...
AI学习指南深度学习篇-卷积层详解
AI学习指南深度学习篇-卷积层详解 一、引言 随着人工智能技术的不断发展,深度学习作为人工智能领域的热门分支之一,正在逐渐成为各个领域的核心技术。而在深度学习中,卷积神经网络(Convolutional Neural Network,CNN…...
2024年TI杯E题-三子棋游戏装置方案分享-jdk123团队-第二弹 手搓机械臂
第一弹赛题的选择与前期方案的准备 opencv调用摄像头bug的解决 机械臂的组装 采用三个舵机,组成一个三自由度的机械臂。 并且利用电磁吸盘的方式,完成对棋子的抓取工作,后面的事实证明,在预算不足的情况下,队友手搓…...
如何在Java、C、Ruby语言中使用Newscatcher API
Newscatcher 世界实时新闻聚合API 一款强大的数据服务工具,它通过先进的网络爬虫技术,实时从全球超过70,000个新闻源聚合新闻内容。这个API能够提供全面、多角度的新闻报道,包括但不限于标题、作者、发布日期、全文内容以及媒体资源链接。它使…...
集合: Collection的成员方法和相关实现类
Collection: - List(有序【指的是存储和取出的顺序是一致的】且可以发生重复,且有索引的概念) - ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全的,效率高。 - …...
过滤器与监听器:深入了解 Java Web 开发中的核心概念
在 Java Web 开发中,过滤器(Filter)和监听器(Listener)是两个重要的组件,它们帮助开发者在请求处理的各个阶段进行预处理和后处理。这篇博客将深入探讨这两个概念,并展示它们如何在实际应用中发…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
