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 …...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
