sqlx概览
开始之前,我们需要一些准备工作,包括:创建用于演示的数据库及数据、创建一个 Rust 项目以及为项目编写一些基础性代码。sqlx的查询构造器
本章将讨论 sqlx 的查询构造器。sqlx 提供了多种查询构造器:`query`、`query_as`、`query!`、`query_as!`、`QueryBuilder`等,合理使用将提升效率。这些查询构造器用来生成数据库所需要的 SQL 语句,不要被它们的名字迷惑了——认为它们是用来查询数据(SQL中的`SELECT`行为)sqlx查询数据
本章将讨论使用 sqlx 执行 `SELECT` 语句,对数据进行查询。sqlx实现增删改
本章将讨论使用 sqlx 进行增删改(`INSERT/DELETE/UPDATE`)操作。使用sqlx的事务实现转账
本章我们将通过用户之间转账来讨论 sqlx 的事务。为了保证转账的完整性、正确性,我们必须使用事务来处理。使用sqlx的QueryBuilder构建复杂、动态的查询
本章我们讨论如何优雅方便地使用 sqlx 构建复杂的、动态的 SQL。sqlx 提供了 [`QueryBuilder`](https://docs.rs/sqlx/latest/sqlx/struct.QueryBuilder.html) 结构体,它可以方便地实现 SQL 的构建。sqlx优雅地实现IN查询
在日常开发中,`IN` 查询是非常常见的需求,你会怎么来处理呢?借助 sqlx 的`QueryBuilder` 可以方便地实现。
sqlx概览
- 1547
- 2023-06-04 06:28:08
开始之前,我们需要一些准备工作,包括:创建用于演示的数据库及数据、创建一个 Rust 项目以及为项目编写一些基础性代码。
示例数据库及数据
本专题我们使用 MySQL 8 数据库,并只使用一张会员(memeber)
表:
你可以在filess.io里创建一个免费的 MySQL 8 实例
字段名 | 说明 |
---|---|
id | 自动编号 |
name | 会员名称 |
dateline | 会员加入时间 |
balance | 账户余额 |
types | 会员类型。在 Rust 中使用枚举,而 MySQL 中使用 TINYINT 。你将看到如何为这两者建立映射。 |
is_del | 是否删除 |
表结构如下:
CREATE TABLE member (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(30) NOT NULL COMMENT '会员名称',
dateline DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '加入时间',
balance INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '账户余额',
types TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '会员类型',
is_del BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否删除',
UNIQUE(name)
) ENGINE=INNODB CHARSET=UTF8MB4 COLLATE=utf8mb4_unicode_ci;
创建项目及依赖
使用 cargo 创建名为 axum-sqlx
的项目:
cargo new axum-sqlx
并加上依赖:
[dependencies]
tokio = {version="1",features=["full"]}
axum = "0.6"
serde = {version="1", features=["derive"]}
chrono = {version="0.4", features=["serde"]}
sqlx = { version = "0.6", features = [ "runtime-tokio-native-tls", "mysql","chrono", "macros" ] }
dotenv = "0.15"
config = "0.13"
tracing = "0.1"
tracing-subscriber = "0.3"
这里对 sqlx
的 features
进行简要说明:
runtime-tokio-native-tls
:使用tokio
运行时,以及使用原生的tls
,在 debian/ubuntu 中,通常由libssl-dev
提供。mysql
:MySQL 数据库chrono
:支持将chronon
映射到 MySQL 时间相关的数据类型macros
:开启query!
等宏的支持
基础性代码
基础性代码无非就是配置文件 、错误处理、状态共享、日志等,在和其它专题的相差不大,这里不再重复。我们重点看一下数据模型的定义:
枚举 MemberTypes
#[derive(Debug, Default, Deserialize, Serialize, sqlx::Type, Clone)]
#[repr(u8)]
pub enum MemberTypes {
#[default]
/// 普通会员
Normal,
/// 白银会员
Silver,
/// 黄金会员
Gold,
/// 钻石会员
Diamond,
}
#[derive(sqlx::Type)]
:用于将这个枚举声明为 sqlx 的类型#[repr(u8)]
:将枚举值的类型替换为u8
有了以上两步,MemberTypes
就能成功通过 sqlx 映射为数据库的 TINYINT UNSIGNED
类型了。
想一想:PostgreSQL 并没有
UNSIGNED
,所以它只能映射为i8
,因此例中的#[repr(u8)]
应该改为#[repr(i8)]
想一想:PostgreSQL 并没有 UNSIGNED
,所以它只能映射为 i8
,因此例中的 #[repr(u8)]
应该改为 #[repr(i8)]
结构体 Member
#[derive(Debug, Default, Deserialize, Serialize, sqlx::FromRow)]
pub struct Member {
pub id: u32,
pub name: String,
pub dateline: chrono::DateTime<chrono::Local>,
pub balance: u32,
pub types: MemberTypes,
pub is_del: bool,
}
#[derive(sqlx::FromRow)]
:使 sqlx 具有自动将查询结果映射到结构体的功能(比如query_as()
)pub dateline: chrono::DateTime<chrono::Local>
:将数据库中的DATETIME
类型映射到 rust 中的chrono::DateTime<chrono::Local>
类型pub types: MemberTypes
:将数据库中的TINYINT UNSIGNED
映射到 rust 中的枚举
想一想:和 MySQL 的
DATETIME
类似,PostgreSQL 中的TIMESTAMPTZ
也可以映射到chrono::DateTime<T>
想一想:和 MySQL 的 DATETIME
类似,PostgreSQL 中的 TIMESTAMPTZ
也可以映射到 chrono::DateTime<T>
本章代码位于01/准备工作分支。