【rust】8、连接数据库:sqlx

sqlx 是 rust 的数据库访问工具, 本身并不是 orm,但常见的 orm 都是基于它实现的。其有如下特点:

  • 支持异步,适合高并发
  • 编译时检查:cargo build 时检查执行 sql,校验响应值
  • 支持多数据库:mysql、pg、sqlite 等
  • 支持主流 rust 运行时:tokio、async-std、actix、native-tls、rustls等
  • 内置连接池

一、数据库、依赖、环境变量

本文操作 pg,首先建表

sql 复制代码
DROP TABLE IF EXISTS course;
CREATE TABLE course (
    id INT8 NOT NULL,
    teacher_id INT4 NOT NULL,
    name VARCHAR(255) NOT NULL,
    time DATE DEFAULT NOW()
);
INSERT INTO course VALUES (1, 11, 'cml', '2022-03-25');
INSERT INTO course VALUES (2, 22, 'cc', '2022-03-25');
INSERT INTO course VALUES (3, 33, 'mm', '2022-03-25');
ALTER TABLE course ADD CONSTRAINT course_pkey PRIMARY KEY (id);

用 cargo new 新建项目,添加依赖:

bash 复制代码
cargo add sqlx -F postgres -F runtime-tokio-rustls -F macros -F chrono
cargo add dotenv # 环境变量工具。本例中将使用此工具处理数据库连接字符串。
cargo add chrono -F serde # 时间工具
cargo add serde -F derive # 序列化
cargo add actix-web # actix 运行时
cargo add actix-rt # actix 运行时

环境变量

数据库地址可以放在配置文件里,例如在根目录新建一个 .env 文件,内容如下:

bash 复制代码
DATABASE_URL=postgres://cml:123456@192.168.1.239:5432/postgres

二、增删改查

2.1 完整示例

  • dotenv().ok():在访问环境变量之前检查一下,防止因读取环境变量失败导致程序 panic。
  • env::var("DATABASE_URL"):读取环境变量文件中的数据库连接字符串
  • PgPoolOptions::new().connect():实例化一个数据库连接池
  • sqlx::query!("sql") .fetch_all(&pool):执行sql语句

工程目录结构:

bash 复制代码
│  .env
│  Cargo.toml 
├─src
│      main.rs

示例代码:

rust 复制代码
use chrono::NaiveDate;
use dotenv::dotenv;
use sqlx::postgres::PgPoolOptions;
use std::env;

#[derive(Debug)]
pub struct Course {
    pub id: i64,
    pub teacher_id: i32,
    pub name: String,
    pub time: Option<NaiveDate>,
}

#[actix_rt::main]
async fn main() -> Result<(), sqlx::Error> {
    println!("Hello, world!");
    dotenv().ok();
    读取所有的环境变量
    // for (key, value) in env::vars() {
    //     println!("环境变量内容:{}: {}", key, value);
    // }
    let connection_str = env::var("DATABASE_URL")
        .expect("数据库连接字符串获取失败,请检查env文件是否已配置数据库连接字符串");
    println!("数据库连接字符串是:{}", connection_str);
    let pool = PgPoolOptions::new()
        .max_connections(5)
        .connect(&connection_str)
        .await?;
    println!("db_pool is : {:?}", pool);
    //查询所有
    let list = sqlx::query!("select * from course")
        .fetch_all(&pool)
        .await?;
    let mut vec = vec![];
    for row in list {
        vec.push(Course {
            id: row.id,
            teacher_id: row.teacher_id,
            name: row.name,
            time: row.time,
        })
    }
    println!("数据库中的所有数据:{:#?}", vec);
    //查询单个
    let list2 = sqlx::query!(r#"select * from course where id = $1"#, 1)
        .fetch_all(&pool)
        .await?;
    let mut vec2 = vec![];
    for row in list2 {
        vec2.push(Course {
            id: row.id,
            teacher_id: row.teacher_id,
            name: row.name,
            time: row.time,
        })
    }
    println!("查询单个{:#?}", vec2);
    // 增加
    let insert = sqlx::query!(
        r#"INSERT INTO course VALUES ($1, $2, $3)"#,
        100000,
        11,
        "gg"
    )
    .fetch_all(&pool)
    .await?;
    // 更新
    let update = sqlx::query!(r#"update course set name=$1"#, "ogg")
        .fetch_all(&pool)
        .await?;
    Ok(())
}

// cargo r
Hello, world!
数据库连接字符串是:postgres://postgres:pass@ip:5432/postgres
db_pool is : Pool { size: 1, num_idle: 1, is_closed: false, options: PoolOptions { max_connections: 5, min_connections: 0, connect_timeout: 30s, max_lifetime: Some(1800s), idle_timeout: Some(600s), test_before_acquire: true } }
数据库中的所有数据:[
    Course {
        id: 1,
        teacher_id: 11,
        name: "cml",
        time: Some(
            2022-03-25,
        ),
    },
    Course {
        id: 2,
        teacher_id: 22,
        name: "cc",
        time: Some(
            2022-03-25,
        ),
    },
    Course {
        id: 3,
        teacher_id: 33,
        name: "mm",
        time: Some(
            2022-03-25,
        ),
    },
]
查询单个[
    Course {
        id: 1,
        teacher_id: 11,
        name: "cml",
        time: Some(
            2022-03-25,
        ),
    },
]

// 执行完时,查询数据库如下:
postgres=# select * from course;
   id   | teacher_id | name |    time
--------+------------+------+------------
      1 |         11 | ogg  | 2022-03-25
      2 |         22 | ogg  | 2022-03-25
      3 |         33 | ogg  | 2022-03-25
 100000 |         11 | ogg  | 2024-02-21
(4 rows)

参考:https://www.cnblogs.com/Naylor/p/16062584.html

2.2 query

rust 复制代码
let sql = format!(r#"DROP TABLE IF EXISTS {}"#, tmp_table_name);
let r = sqlx::query(&sql).execute(&pool).await?;
println!("sql: {} r: {:?}", sql, r);
相关推荐
TDengine (老段)20 小时前
TDengine 数学函数 DEGRESS 用户手册
大数据·数据库·sql·物联网·时序数据库·iot·tdengine
TDengine (老段)20 小时前
TDengine 数学函数 GREATEST 用户手册
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
安当加密21 小时前
云原生时代的数据库字段加密:在微服务与 Kubernetes 中实现合规与敏捷的统一
数据库·微服务·云原生
爱喝白开水a21 小时前
LangChain 基础系列之 Prompt 工程详解:从设计原理到实战模板_langchain prompt
开发语言·数据库·人工智能·python·langchain·prompt·知识图谱
想ai抽21 小时前
深入starrocks-多列联合统计一致性探查与策略(YY一下)
java·数据库·数据仓库
武子康21 小时前
Java-152 深入浅出 MongoDB 索引详解 从 MongoDB B-树 到 MySQL B+树 索引机制、数据结构与应用场景的全面对比分析
java·开发语言·数据库·sql·mongodb·性能优化·nosql
longgyy21 小时前
5 分钟用火山引擎 DeepSeek 调用大模型生成小红书文案
java·数据库·火山引擎
ytttr8731 天前
C# 仿QQ聊天功能实现 (SQL Server数据库)
数据库·oracle·c#
盒马coding1 天前
第18节-索引-Partial-Indexes
数据库·postgresql
不剪发的Tony老师1 天前
CloudDM:一站式数据库开发管理工具
数据库