Rust如何操作数据库

作为一个Rust新手,想请教大家在实际项目中如何用Rust操作数据库?目前了解到有Diesel和SQLx这样的ORM和查询构建器,但不太清楚它们的优缺点和适用场景。比如:

  1. 在开发Web应用时推荐使用哪个库?
  2. 这两种方式在性能和使用体验上有什么主要区别?
  3. 是否有其他更轻量级的数据库操作方案?
  4. 能否分享一些实际项目中的最佳实践和常见坑点? 希望有经验的前辈能指点迷津,最好能附带简单的代码示例说明基本用法。
2 回复

Rust操作数据库常用库:

  1. Diesel - ORM框架,类型安全,支持PostgreSQL、MySQL、SQLite
  2. SQLx - 异步驱动,编译时检查SQL,支持多种数据库
  3. tokio-postgres - 纯异步PostgreSQL客户端

示例(Diesel):

// 查询用户
let users = users::table.filter(name.eq("张三")).load::<User>(&conn)?;

建议:根据数据库类型和同步/异步需求选择合适库。


在Rust中操作数据库主要通过以下几种方式:

1. 使用数据库驱动库

SQLite

use rusqlite::{Connection, Result};

fn main() -> Result<()> {
    let conn = Connection::open("test.db")?;
    
    // 创建表
    conn.execute(
        "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)",
        [],
    )?;
    
    // 插入数据
    conn.execute(
        "INSERT INTO users (name) VALUES (?1)",
        &["Alice"],
    )?;
    
    // 查询数据
    let mut stmt = conn.prepare("SELECT id, name FROM users")?;
    let users = stmt.query_map([], |row| {
        Ok((row.get::<_, i32>(0)?, row.get::<_, String>(1)?))
    })?;
    
    for user in users {
        let (id, name) = user?;
        println!("User {}: {}", id, name);
    }
    
    Ok(())
}

PostgreSQL

use postgres::{Client, NoTls};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Client::connect("host=localhost user=postgres", NoTls)?;
    
    client.batch_execute("
        CREATE TABLE IF NOT EXISTS users (
            id SERIAL PRIMARY KEY,
            name VARCHAR NOT NULL
        )
    ")?;
    
    client.execute(
        "INSERT INTO users (name) VALUES ($1)",
        &[&"Bob"],
    )?;
    
    for row in client.query("SELECT id, name FROM users", &[])? {
        let id: i32 = row.get(0);
        let name: &str = row.get(1);
        println!("User {}: {}", id, name);
    }
    
    Ok(())
}

2. 使用ORM框架 - Diesel

Diesel是Rust中最流行的ORM框架:

// Cargo.toml 依赖
// diesel = { version = "2.0", features = ["postgres"] }

use diesel::prelude::*;

// 定义模型
#[derive(Queryable, Insertable)]
#[diesel(table_name = users)]
struct User {
    id: i32,
    name: String,
}

// 插入数据
fn create_user(conn: &mut PgConnection, name: &str) -> QueryResult<User> {
    use crate::schema::users;
    
    let new_user = NewUser { name };
    
    diesel::insert_into(users::table)
        .values(&new_user)
        .get_result(conn)
}

// 查询数据
fn get_users(conn: &mut PgConnection) -> QueryResult<Vec<User>> {
    users::table.load::<User>(conn)
}

3. 异步数据库操作 - sqlx

use sqlx::postgres::PgPoolOptions;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let pool = PgPoolOptions::new()
        .connect("postgres://user:pass@localhost/db")
        .await?;
    
    // 查询
    let rows = sqlx::query!("SELECT id, name FROM users WHERE id = $1", 1)
        .fetch_all(&pool)
        .await?;
    
    // 插入
    sqlx::query!("INSERT INTO users (name) VALUES ($1)", "Charlie")
        .execute(&pool)
        .await?;
    
    Ok(())
}

主要库推荐

  • sqlx: 异步、编译时检查的SQL查询
  • Diesel: 功能完整的ORM框架
  • rusqlite: SQLite驱动
  • tokio-postgres: 异步PostgreSQL驱动
  • mysql: MySQL驱动

选择哪种方式取决于项目需求:需要异步操作选sqlx,需要完整ORM功能选Diesel,简单项目可直接使用数据库驱动。

回到顶部