当前位置: 首页 > news >正文

Rust操作MySQL

查询


本部分是对 「Rust入门系列」Rust 中使用 MySQL[1]的学习与记录


  • 经常使用的时间处理库: chrono
  • 流式查询使用: query_iter
  • 输出到Vec使用: query
  • 映射到结构体使用: query_map

  • 获取单条数据使用: query_first
  • 命名参数查询使用: exec_first
CREATE TABLE `student` (
  `id` int(11NOT NULL AUTO_INCREMENT,
  `name` varchar(128NOT NULL,
  `age` int(11NOT NULL,
  `id_card` varchar(128NOT 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" #通配符*表示可以使用任何版本,通常会拉取最新版本;此处需要指定,不使用最新版本
alt

流式查询


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: (i32Stringi32String, 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,83823539022022-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<(i32Stringi32String, 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.prepconn.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())
}

alt

和上面一节一样,命名参数在这里使用了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(20170504),
     }).unwrap()
    }
}
alt

获取生成的主键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(20220504),
}).unwrap();

    println!("新插入的记录的主键为: {}", conn.last_insert_id())
}

新插入的记录的主键为: 13
alt

更新和删除


类似于插入操作

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(20381231),
     "id" => 10,
}).unwrap();


    let stmt = conn.prep("delete from student where id=:id").unwrap();

    conn.exec_drop(&stmt, params! {
    "id" => 12,
}).unwrap();
}
alt

参考资料

[1]

「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]的学习与记录 经常使用的时间处理库&#xff1a; chrono 流式查询使用&#xff1a; query_iter 输出到Vec使用&#xff1a; query 映射到结构体使用&#xff1a; query_map 获取单条数据使用&#xff1a; query_first 命名…...

JAVA面试总结-Redis篇章(二)——缓存击穿

JAVA面试总结-Redis篇章&#xff08;二&#xff09; 缓存击穿解决方案一&#xff1a;互斥锁解决方案二&#xff1a;逻辑过期![在这里插入图片描述](https://img-blog.csdnimg.cn/176dfab3e26044a9a730fabea4314e8e.png) 缓存击穿 解决方案一&#xff1a;互斥锁 解决方案二&…...

Spring相关知识点

概述 分层的轻量级的全栈开源框架 展示层SprigMVC 持久层 Spring JDBCTemplate 业务层事务管理 注&#xff1a; 轻量级&#xff1a;API简单 全栈&#xff1a;各层都有相应解决方案 在Spring的体系结构中&#xff0c;由上而下&#xff0c;逐层依赖 Spring相当于是一个粘合剂&…...

Nginx专题--反向代理(未完成)

反向代理   正向代理&#xff1a;如果把局域网外的 Internet 想象成一个巨大的资源库&#xff0c;则局域网中的客户端要访问 Internet&#xff0c;则需要通过代理服务器来访问&#xff0c;这种代理服务就称为正向代理。 反向代理&#xff1a;其实客户端对代理是无感知的&…...

什么是搜索引擎?2023 年搜索引擎如何运作?

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

Spring系列一:spring的安装与使用

文章目录 &#x1f49e; 官方资料&#x1f34a;Spring5下载&#x1f34a;文档介绍 &#x1f49e;Spring5&#x1f34a;内容介绍&#x1f34a;重要概念 &#x1f49e;快速入门&#x1f34a;Spring操作演示&#x1f34a;类加载路径&#x1f34a;Debug配置&#x1f34a;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" &#xff08;后面可以直接托文件到终端&#…...

【压测指南|压力测试核心性能指标及行业标准】

文章目录 压力测试核心性能指标及行业标准指标1&#xff1a;响应时间指标2&#xff1a;吞吐量&#xff08;TPS)指标3&#xff1a;失败率总结&#xff1a; 压力测试核心性能指标及行业标准 在做压力测试时&#xff0c;新手测试人员常常在看报告时倍感压力&#xff1a;这么多性能…...

spark-submit --files

一、原理 spark-submit --files通常用来加载外部资源文件&#xff0c;在driver和executor进程中进行访问 –files和–jars基本相同 二、使用步骤 2.1 添加文件 spark-submit --files file_paths 其中file_paths可为多种方式&#xff1a;file: | hdfs:// | http:// | ftp:// |…...

应该选云服务器还是物理服务器

应该选云服务器还是物理服务器 一、为什么需要云服务器或独立服务器取代共享主机 在最早之前&#xff0c;大多数的网站都是共享主机开始的&#xff0c;这里也包含了云虚拟机。这一类的站点还有其他站点都会共同托管在同一台服务器上。但是这种共享机只适用于小的网站&#xff…...

【iOS】动态链接器dyld

参考&#xff1a;认识 dyld &#xff1a;动态链接器 dyld简介 dyld&#xff08;Dynamic Linker&#xff09;是 macOS 和 iOS 系统中的动态链接器&#xff0c;它是负责在运行时加载和链接动态共享库&#xff08;dylib&#xff09;或可执行文件的组件。在 macOS 系统中&#xf…...

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插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 字符串string的比较有很多方法&#xff0c;比如&#xff1a; …...

vue3+ts+element-plus 之使用node.js对接mysql进行表格数据展示

vue3tselement-plus axiosnode.jsmysql开发管理系统之表格展示 ✏️ 1. 新建一个node项目* 初始化node* 安装可能用到的依赖* 配置文件目录* 添加路由router1. 添加router.js文件&#xff0c;添加一个test目录2. 修改app.js ,引入router&#x1f4d2; 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的相互转换

这种方法只能解决非常简单的转换&#xff0c;更难的SMILES之间应该是无法直接转换&#xff0c;我可能很多人都使用神经网络解决 &#xff0c;暂时还没仔细看&#xff0c;后面再仔细看吧... 简单的转换&#xff1a; import urllib.error import urllib.parse import urllib.re…...

逻辑回归概述

逻辑回归介绍 1. 逻辑回归的应用场景 逻辑回归(Logistic Regression)是机器学习中的 一种分类模型 ,逻辑回归是一种分类算法,虽然名字中带有回归。由于算法的简单和高效,在实际中应用非常广泛 广告点击率是否为垃圾邮件是否患病信用卡账单是否会违约 逻辑回归就是解决二…...

React 框架下自己写一个braft编辑器,然后将编辑器内容展示在网页端

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

基于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 …...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

深度解析云存储:概念、架构与应用实践

在数据爆炸式增长的时代&#xff0c;传统本地存储因容量限制、管理复杂等问题&#xff0c;已难以满足企业和个人的需求。云存储凭借灵活扩展、便捷访问等特性&#xff0c;成为数据存储领域的主流解决方案。从个人照片备份到企业核心数据管理&#xff0c;云存储正重塑数据存储与…...