Rust操作MySQL
查询
本部分是对 「Rust入门系列」Rust 中使用 MySQL[1]的学习与记录
-
经常使用的时间处理库: chrono
-
流式查询使用: query_iter
-
输出到Vec使用: query
-
映射到结构体使用: query_map
-
获取单条数据使用: query_first
-
命名参数查询使用: exec_first
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
`age` int(11) NOT NULL,
`id_card` varchar(128) NOT NULL,
`last_update` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 插入测试数据
insert into student (name, age, id_card, last_update) values ('张三', 23, '123456789X', CURRENT_DATE());
insert into student (name, age, id_card, last_update) values ('李四', 24, '8382353902', CURRENT_DATE())
注意,mysql[2]这个crate新版本demo有问题,文档的更新速度跟不上代码的修改脚步..
需要指定版本:
[dependencies]
mysql = "20.0.0" #通配符*表示可以使用任何版本,通常会拉取最新版本;此处需要指定,不使用最新版本

流式查询
use chrono::prelude::*;// 用来处理日期
use mysql::*;
use mysql::prelude::*;
fn main() {
let url = "mysql://root:12345678@localhost:3306/shuang";
let pool = Pool::new(url).unwrap(); // 获取连接池
let mut conn = pool.get_conn().unwrap();// 获取链接
conn.query_iter("select * from student")
.unwrap()
.for_each(|row| {
let r: (i32, String, i32, String, NaiveDate) = from_row(row.unwrap());
println!("{}, {},{},{}, {:?}", r.0, r.1, r.2, r.3, r.4);
});
}
row的类型是mysql_common::row::Row
,其把数据以字节的形式存储。
所以需将低级的字节转换成想要的类型 如i32,String,这里使用了from_row
。注意,转换后的数据以元组的形式返回,其中每一项和选择列的顺序相同。
输出:
1, 张三,23,123456789X, 2022-04-26
2, 李四,24,8382353902, 2022-04-26
流式查询
其实还可以将查询结果收集到Vec中。 Vec中的每个元素都是一个元组。
query函数已经将字节转换为选择的数据类型,因此不需要再转换了。 需要注意的是,这里必须明确元组的数据类型(如此处是 Vec<(i32, String, i32, String, NaiveDate)>
)。 否则,编译器没办法做转换。
use chrono::prelude::*;// 用来处理日期
use mysql::*;
use mysql::prelude::*;
fn main() {
let url = "mysql://root:12345678@localhost:3306/shuang";
let pool = Pool::new(url).unwrap(); // 获取连接池
let mut conn = pool.get_conn().unwrap();// 获取链接
// 输出到Vec
let res: Vec<(i32, String, i32, String, NaiveDate)> =
conn.query("select * from student").unwrap();
for r in res {
println!("{}, {},{},{}, {:?}", r.0, r.1, r.2, r.3, r.4);
}
}
映射结果到结构体
如果表的列数很多,使用元组容易混淆,更普遍的做法是定义一个结构体。
如下定义一个Student结构体, 然后可以用query_map
将查询结果映射到Student中。
不需要指定数据类型,编译器会根据Student类型自动推导
use chrono::prelude::*;// 用来处理日期
use mysql::*;
use mysql::prelude::*;
fn main() {
let url = "mysql://root:12345678@localhost:3306/shuang";
let pool = Pool::new(url).unwrap(); // 获取连接池
let mut conn = pool.get_conn().unwrap();// 获取链接
// 将结果映射到提前定义好的结构体
struct Student {
id: u64,
name: String,
age: u16,
id_card: String,
last_changed_on: NaiveDate,
}
let res = conn.query_map(
"select * from student",
|(id, name, age, id_card, update)| Student {
id: id,
name: name,
age: age,
id_card: id_card,
last_changed_on: update,
},
).expect("Query failed.");
for i in res {
println!(
"{}, {},{},{}, {:?}",
i.id, i.name, i.age, i.id_card, i.last_changed_on
)
}
}
单条数据查询
查询特定数据行,可能会出现下面几种情况:
-
找到,返回实际数据 -
没有找到行 -
发生错误
所以,使用query_first
函数返回的是Option的结果。 需要将其解包两次才可以获取实际的行数据:
use chrono::prelude::*;// 用来处理日期
use mysql::*;
use mysql::prelude::*;
fn main() {
let url = "mysql://root:12345678@localhost:3306/shuang";
let pool = Pool::new(url).unwrap(); // 获取连接池
let mut conn = pool.get_conn().unwrap();// 获取链接
struct Student {
id: u64,
name: String,
age: u16,
id_card: String,
last_changed_on: NaiveDate,
}
// 条件查询,查询单个数据
let res = conn.query_first("select * from student where name = '张三'")
.map(
// Unpack Result
|row| {
row.map(|(id, name, age, id_card, update)| Student {
id: id,
name: name,
age: age,
id_card: id_card,
last_changed_on: update,
})
},
);
match res.unwrap() {
Some(student) => println!(
"{}, {},{},{}, {:?}",
student.id, student.name, student.age, student.id_card, student.last_changed_on
),
None => println!("Sorry no student found."),
}
}
命名参数的使用
use chrono::prelude::*;// 用来处理日期
use mysql::*;
use mysql::prelude::*;
fn main() {
let url = "mysql://root:12345678@localhost:3306/shuang";
let pool = Pool::new(url).unwrap(); // 获取连接池
let mut conn = pool.get_conn().unwrap();// 获取链接
struct Student {
id: u64,
name: String,
age: u16,
id_card: String,
last_changed_on: NaiveDate,
}
let res = conn
.exec_first(
"select * from student where name = :name",
params! {
"name" => "李四"
},
)
.map(
// Unpack Result
|row| {
row.map(|(id, name, age, id_card, update)| Student {
id: id,
name: name,
age: age,
id_card: id_card,
last_changed_on: update,
})
},
);
match res.unwrap() {
Some(student) => println!(
"{}, {},{},{}, {:?}",
student.id, student.name, student.age, student.id_card, student.last_changed_on
),
None => println!("Sorry no student found."),
}
}
写操作
本部分是对 Rust使用MySQL数据库02[3]的学习与记录
-
插入数据使用 conn.exec_drop()
-
使用预编译语句插入大量数据, conn.prep()
-
使用 conn.last_insert_id()
可以获取主键
-
更新和删除也使用 conn.prep
和conn.exec_drop
插入新数据
use chrono::prelude::*;
// 用来处理日期
use mysql::*;
use mysql::prelude::*;
fn main() {
let url = "mysql://root:12345678@localhost:3306/shuang";
let pool = Pool::new(url).unwrap(); // 获取连接池
let mut conn = pool.get_conn().unwrap();// 获取链接
conn.exec_drop(
"INSERT INTO student (name, age, id_card, last_update) VALUES (:name, :age, :id_card, :last_update)",
params! {
"name" => "王五",
"age" => 28,
"id_card" => "66666688",
"last_update" => today(),
}).unwrap();
}
fn today() -> NaiveDate {
let l = Local::today();
NaiveDate::from_ymd(l.year(), l.month(), l.day())
}

和上面一节一样,命名参数在这里使用了params宏的语法
exec_drop
方法中的drop表示没有返回结果
用于执行插入/更新/删除的sql
使用预编译语句
使用conn.prep
将sql编译成预编译语句。
use chrono::prelude::*;
// 用来处理日期
use mysql::*;
use mysql::prelude::*;
fn main() {
let url = "mysql://root:12345678@localhost:3306/shuang";
let pool = Pool::new(url).unwrap(); // 获取连接池
let mut conn = pool.get_conn().unwrap();// 获取链接
let stmt = conn.prep("INSERT INTO student (name, age, id_card, last_update) VALUES (:name, :age, :id_card, :last_update)")
.unwrap();
for i in 1..10 {
conn.exec_drop(&stmt, params! {
"name" => "dashen",
"age" => 18 + i,
"id_card" => "1234565X",
"last_update" => NaiveDate::from_ymd(2017, 05, 04),
}).unwrap()
}
}

获取生成的主键id
可以通过conn.last_insert_id()
方法获取到新记录的主键id,该方法将返回的一个类型为u64 的值
use chrono::prelude::*;
// 用来处理日期
use mysql::*;
use mysql::prelude::*;
fn main() {
let url = "mysql://root:12345678@localhost:3306/shuang";
let pool = Pool::new(url).unwrap(); // 获取连接池
let mut conn = pool.get_conn().unwrap();// 获取链接
conn.exec_drop("INSERT INTO student (name, age, id_card, last_update) VALUES (:name, :age, :id_card, :last_update)", params! {
"name" => "fliter",
"age" => 29,
"id_card" => "88888888",
"last_update" => NaiveDate::from_ymd(2022, 05, 04),
}).unwrap();
println!("新插入的记录的主键为: {}", conn.last_insert_id())
}
新插入的记录的主键为: 13

更新和删除
类似于插入操作
use chrono::prelude::*;
// 用来处理日期
use mysql::*;
use mysql::prelude::*;
fn main() {
let url = "mysql://root:12345678@localhost:3306/shuang";
let pool = Pool::new(url).unwrap(); // 获取连接池
let mut conn = pool.get_conn().unwrap();// 获取链接
let stmt = conn.prep("update student set name=:name, last_update=:last_update where id=:id")
.unwrap();
conn.exec_drop(&stmt, params! {
"name" => "新名字",
"last_update" => NaiveDate::from_ymd(2038, 12, 31),
"id" => 10,
}).unwrap();
let stmt = conn.prep("delete from student where id=:id").unwrap();
conn.exec_drop(&stmt, params! {
"id" => 12,
}).unwrap();
}

参考资料
「Rust入门系列」Rust 中使用 MySQL: https://rustmagazine.github.io/rust_magazine_2021/chapter_3/rust-mysql.html
[2]mysql: https://crates.io/crates/mysql
[3]Rust使用MySQL数据库02: https://www.modb.pro/db/179746
本文由 mdnice 多平台发布
相关文章:

Rust操作MySQL
查询 本部分是对 「Rust入门系列」Rust 中使用 MySQL[1]的学习与记录 经常使用的时间处理库: chrono 流式查询使用: query_iter 输出到Vec使用: query 映射到结构体使用: query_map 获取单条数据使用: query_first 命名…...

JAVA面试总结-Redis篇章(二)——缓存击穿
JAVA面试总结-Redis篇章(二) 缓存击穿解决方案一:互斥锁解决方案二:逻辑过期 缓存击穿 解决方案一:互斥锁 解决方案二&…...
Spring相关知识点
概述 分层的轻量级的全栈开源框架 展示层SprigMVC 持久层 Spring JDBCTemplate 业务层事务管理 注: 轻量级:API简单 全栈:各层都有相应解决方案 在Spring的体系结构中,由上而下,逐层依赖 Spring相当于是一个粘合剂&…...
Nginx专题--反向代理(未完成)
反向代理 正向代理:如果把局域网外的 Internet 想象成一个巨大的资源库,则局域网中的客户端要访问 Internet,则需要通过代理服务器来访问,这种代理服务就称为正向代理。 反向代理:其实客户端对代理是无感知的&…...

什么是搜索引擎?2023 年搜索引擎如何运作?
目录 什么是搜索引擎?搜索引擎的原理什么是搜索引擎爬取?什么是搜索引擎索引?什么是搜索引擎检索?什么是搜索引擎排序? 搜索引擎的目的是什么?搜索引擎如何赚钱?搜索引擎如何建立索引?网页抓取文本处理建…...

Spring系列一:spring的安装与使用
文章目录 💞 官方资料🍊Spring5下载🍊文档介绍 💞Spring5🍊内容介绍🍊重要概念 💞快速入门🍊Spring操作演示🍊类加载路径🍊Debug配置🍊Spring容器…...

Ubuntu--科研工具系列
翻译系列 pot-desktop github链接: https://github.com/pot-app/pot-desktop 下载deb Releases pot-app/pot-desktop GitHub 安装过程 在下载好的deb目录下打开终端(自动安装依赖) sudo apt install "XXX.deb" (后面可以直接托文件到终端&#…...

【压测指南|压力测试核心性能指标及行业标准】
文章目录 压力测试核心性能指标及行业标准指标1:响应时间指标2:吞吐量(TPS)指标3:失败率总结: 压力测试核心性能指标及行业标准 在做压力测试时,新手测试人员常常在看报告时倍感压力:这么多性能…...
spark-submit --files
一、原理 spark-submit --files通常用来加载外部资源文件,在driver和executor进程中进行访问 –files和–jars基本相同 二、使用步骤 2.1 添加文件 spark-submit --files file_paths 其中file_paths可为多种方式:file: | hdfs:// | http:// | ftp:// |…...
应该选云服务器还是物理服务器
应该选云服务器还是物理服务器 一、为什么需要云服务器或独立服务器取代共享主机 在最早之前,大多数的网站都是共享主机开始的,这里也包含了云虚拟机。这一类的站点还有其他站点都会共同托管在同一台服务器上。但是这种共享机只适用于小的网站ÿ…...

【iOS】动态链接器dyld
参考:认识 dyld :动态链接器 dyld简介 dyld(Dynamic Linker)是 macOS 和 iOS 系统中的动态链接器,它是负责在运行时加载和链接动态共享库(dylib)或可执行文件的组件。在 macOS 系统中…...
RocketMQ集成Springboot --Chapter1
RocketMQ集成Springboot 三种消息发送方式 生产者 引入依赖 <!--⽗⼯程--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.2.RELEASE</version><…...

【Unity3D日常开发】Unity3D中比较string字符串的常用方法
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 字符串string的比较有很多方法,比如: …...

vue3+ts+element-plus 之使用node.js对接mysql进行表格数据展示
vue3tselement-plus axiosnode.jsmysql开发管理系统之表格展示 ✏️ 1. 新建一个node项目* 初始化node* 安装可能用到的依赖* 配置文件目录* 添加路由router1. 添加router.js文件,添加一个test目录2. 修改app.js ,引入router📒 3. 启动并在浏览器打开 * …...

华为eNSP:isis配置跨区域路由
一、拓扑图 二、路由器的配置 1、配置接口IP AR1: <Huawei>system-view [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 1.1.1.1 24 [Huawei-GigabitEthernet0/0/0]q AR2: [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 1.1.1.2 24 [Huawe…...
IUPAC和SMILES的相互转换
这种方法只能解决非常简单的转换,更难的SMILES之间应该是无法直接转换,我可能很多人都使用神经网络解决 ,暂时还没仔细看,后面再仔细看吧... 简单的转换: import urllib.error import urllib.parse import urllib.re…...
逻辑回归概述
逻辑回归介绍 1. 逻辑回归的应用场景 逻辑回归(Logistic Regression)是机器学习中的 一种分类模型 ,逻辑回归是一种分类算法,虽然名字中带有回归。由于算法的简单和高效,在实际中应用非常广泛 广告点击率是否为垃圾邮件是否患病信用卡账单是否会违约 逻辑回归就是解决二…...

React 框架下自己写一个braft编辑器,然后将编辑器内容展示在网页端
1.首先自己写一个编辑器 输入文字; 支持选择表情; 可添加小程序链接;可添加网页链接;并且可以编辑删除;效果如下 2.输入完毕后,点击文本输入框保存,将便携式内容回显, 渲染时…...

基于DNN深度学习网络的OFDM+QPSK信号检测算法matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................................. Transmitt…...
学生管理系统-05封装选项卡
一、选项卡的添加 1、在router/index.js修改之前的动态添加二级路由的代码 router.addRoute("homeName",{ path:routeObj.path, component:()=>import(`@/views${routeObj.permission}.vue`), meta:{ name:routeObj.title …...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...

基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...