Rust如何操作数据库

刚开始学习Rust,想用Rust连接和操作数据库,但不知道从何下手。请问有哪些常用的Rust数据库操作库推荐?比如MySQL或PostgreSQL该怎么连接?需要特别注意哪些Rust特有的并发安全或所有权问题吗?能否给个简单的CRUD示例代码?最好能对比下不同库的优缺点,比如diesel和sqlx哪个更适合新手入门?

2 回复

Rust操作数据库主要通过第三方库实现:

  • Diesel:最流行的ORM,支持PostgreSQL、MySQL、SQLite
  • SQLx:异步数据库驱动,支持多种数据库
  • SeaORM:新兴的异步ORM

安装依赖后,配置数据库连接,即可执行查询和事务操作。


在Rust中操作数据库,主要通过以下几个步骤实现:

1. 选择数据库驱动

根据数据库类型选择相应的Rust库:

PostgreSQL

// Cargo.toml
// [dependencies]
// tokio-postgres = "0.7"
// postgres-native-tls = "0.5"

use tokio_postgres::{NoTls, Error};

#[tokio::main]
async fn main() -> Result<(), Error> {
    let (client, connection) = tokio_postgres::connect(
        "host=localhost user=postgres password=123456 dbname=test",
        NoTls,
    ).await?;

    tokio::spawn(async move {
        if let Err(e) = connection.await {
            eprintln!("connection error: {}", e);
        }
    });

    // 执行查询
    let rows = client
        .query("SELECT id, name FROM users WHERE id = $1", &[&1i32])
        .await?;

    for row in rows {
        let id: i32 = row.get(0);
        let name: &str = row.get(1);
        println!("id: {}, name: {}", id, name);
    }

    Ok(())
}

MySQL

// Cargo.toml
// [dependencies]
// mysql = "*"

use mysql::*;
use mysql::prelude::*;

fn main() -> Result<()> {
    let url = "mysql://username:password@localhost:3306/database";
    let pool = Pool::new(url)?;
    let mut conn = pool.get_conn()?;

    // 查询数据
    let users: Vec<(i32, String)> = conn
        .query_map("SELECT id, name FROM users", |(id, name)| (id, name))?;

    for (id, name) in users {
        println!("id: {}, name: {}", id, name);
    }

    // 插入数据
    conn.exec_drop(
        "INSERT INTO users (name) VALUES (?)",
        ("Alice",),
    )?;

    Ok(())
}

2. 使用ORM框架(推荐)

Diesel(最流行的Rust ORM)

// Cargo.toml
// [dependencies]
// diesel = { version = "2.0", features = ["postgres"] }
// dotenvy = "0.15"

use diesel::prelude::*;
use diesel::pg::PgConnection;
use dotenvy::dotenv;
use std::env;

pub fn establish_connection() -> PgConnection {
    dotenv().ok();
    let database_url = env::var("DATABASE_URL")
        .expect("DATABASE_URL must be set");
    PgConnection::establish(&database_url)
        .expect(&format!("Error connecting to {}", database_url))
}

// 定义模型
#[derive(Queryable)]
struct User {
    pub id: i32,
    pub name: String,
    pub email: String,
}

// 查询示例
fn get_users() -> Vec<User> {
    use crate::schema::users::dsl::*;
    
    let connection = &mut establish_connection();
    users
        .filter(email.like("%@example.com%"))
        .limit(10)
        .load::<User>(connection)
        .expect("Error loading users")
}

3. 异步操作

对于异步应用,可以使用sqlx

// Cargo.toml
// [dependencies]
// sqlx = { version = "0.7", features = ["postgres", "runtime-tokio-rustls"] }
// tokio = { version = "1", features = ["full"] }

use sqlx::postgres::PgPoolOptions;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let pool = PgPoolOptions::new()
        .connect("postgres://user:pass@localhost/db")
        .await?;

    let row: (i64,) = sqlx::query_as("SELECT $1")
        .bind(150_i64)
        .fetch_one(&pool)
        .await?;

    assert_eq!(row.0, 150);
    Ok(())
}

主要库推荐

  • Diesel: 功能完整的ORM,编译时检查查询
  • sqlx: 异步数据库工具包,零开销
  • tokio-postgres: PostgreSQL的异步客户端
  • mysql: MySQL客户端
  • rusqlite: SQLite客户端

选择哪个库取决于你的具体需求:需要完整ORM功能选Diesel,需要异步支持选sqlx,简单项目可选直接使用数据库客户端。

回到顶部