当前位置: 首页 > 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 …...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开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 …...