Ormer
Home
Quick Start
GitHub
  • 简体中文
  • English
Home
Quick Start
GitHub
  • 简体中文
  • English
  • Introduction to Ormer
  • Quick Start
  • Model Definition
  • Database Connection
  • Data Operations
  • Query Builder
  • Advanced Queries
  • Transaction Management
  • Connection Pool

Data Operations

This document details Ormer's CRUD (Create, Read, Update, Delete) operations.

Insert Data (Create)

Single Insert

Use the insert() method to insert a single record:

#[derive(Debug, Model)]
#[table = "users"]
struct User {
    #[primary(auto)]
    id: i32,
    name: String,
    age: i32,
    email: Option<String>,
}

// Insert single record
db.insert(&User {
    id: 1,
    name: "Alice".to_string(),
    age: 25,
    email: Some("alice@example.com".to_string()),
}).await?;

Batch Insert

Using Vec

let users = vec![
    User {
        id: 1,
        name: "Alice".to_string(),
        age: 25,
        email: None,
    },
    User {
        id: 2,
        name: "Bob".to_string(),
        age: 30,
        email: Some("bob@example.com".to_string()),
    },
    User {
        id: 3,
        name: "Charlie".to_string(),
        age: 35,
        email: Some("charlie@example.com".to_string()),
    },
];

db.insert(&users).await?;

Using Array

db.insert(&[
    User { id: 1, name: "Alice".to_string(), age: 25, email: None },
    User { id: 2, name: "Bob".to_string(), age: 30, email: None },
]).await?;

Using Slice

let users = vec![/* ... */];
db.insert(&users[..]).await?;

Insert or Update (Upsert)

Automatically update existing records when encountering duplicate keys:

// First insert
db.insert_or_update(&User {
    id: 1,
    name: "Alice".to_string(),
    age: 25,
    email: Some("alice@example.com".to_string()),
}).await?;

// Update existing record
db.insert_or_update(&User {
    id: 1,  // Same ID
    name: "Alice Smith".to_string(),  // Update name
    age: 26,  // Update age
    email: Some("alice.smith@example.com".to_string()),
}).await?;

Batch insert or update:

db.insert_or_update(&vec![
    User { id: 1, name: "Alice".to_string(), age: 25, email: None },
    User { id: 2, name: "Bob".to_string(), age: 30, email: None },
]).await?;

Read Data (Read)

Query All Records

let all_users: Vec<User> = db
    .select::<User>()
    .collect::<Vec<_>>()
    .await?;

Conditional Query

See Query Builder Documentation for details.

Basic example:

// Users aged 18 or older
let adults: Vec<User> = db
    .select::<User>()
    .filter(|u| u.age.ge(18))
    .collect()
    .await?;

// Name match
let alice: Vec<User> = db
    .select::<User>()
    .filter(|u| u.name.eq("Alice".to_string()))
    .collect()
    .await?;

Sorting and Pagination

// Sort by name ascending, get first 10
let users: Vec<User> = db
    .select::<User>()
    .order_by(|u| u.name.asc())
    .range(0..10)
    .collect()
    .await?;

// Sort by age descending, paginated
let page2: Vec<User> = db
    .select::<User>()
    .order_by_desc(|u| u.age)
    .range(10..20)  // Page 2 (10 per page)
    .collect()
    .await?;

Update Data (Update)

Use the update() method to update records:

Basic Update

let count = db
    .update::<User>()
    .filter(|u| u.age.ge(18))
    .set(|u| u.name, "Adult".to_string())
    .execute()
    .await?;

println!("Updated {} rows", count);

Multiple Fields Update

let count = db
    .update::<User>()
    .filter(|u| u.id.eq(1))
    .set(|u| u.name, "Alice Smith".to_string())
    .set(|u| u.age, 26)
    .set(|u| u.email, Some("alice.smith@example.com".to_string()))
    .execute()
    .await?;

Conditional Update

// Update all users under 18
let count = db
    .update::<User>()
    .filter(|u| u.age.lt(18))
    .set(|u| u.name, "Minor".to_string())
    .execute()
    .await?;

Delete Data (Delete)

Use the delete() method to delete records:

Conditional Delete

let count = db
    .delete::<User>()
    .filter(|u| u.age.lt(18))
    .execute()
    .await?;

println!("Deleted {} rows", count);

Delete Specific Record

let count = db
    .delete::<User>()
    .filter(|u| u.id.eq(1))
    .execute()
    .await?;

Delete All Records

⚠️ Warning: This will delete all data in the table!

let count = db
    .delete::<User>()
    .execute()
    .await?;

Table Management

Create Table

db.create_table::<User>().await?;

This generates a CREATE TABLE IF NOT EXISTS SQL statement.

Drop Table

db.drop_table::<User>().await?;

Generates a DROP TABLE IF EXISTS SQL statement.

Execute Raw SQL

Query and Return Models

let users: Vec<User> = db
    .exec_table::<User>("SELECT * FROM users WHERE age >= 18")
    .await?;

Execute Non-Query SQL

let affected_rows = db
    .exec_non_query("UPDATE users SET name = 'Test' WHERE id = 1")
    .await?;

println!("Affected {} rows", affected_rows);

Complete Example

use ormer::{Database, DbType, Model};

#[derive(Debug, Model)]
#[table = "users"]
struct User {
    #[primary(auto)]
    id: i32,
    name: String,
    age: i32,
    email: Option<String>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db = Database::connect(DbType::Turso, "file:test.db").await?;
    db.create_table::<User>().await?;
    
    // 1. Insert data
    db.insert(&User {
        id: 1,
        name: "Alice".to_string(),
        age: 25,
        email: Some("alice@example.com".to_string()),
    }).await?;
    
    db.insert(&vec![
        User { id: 2, name: "Bob".to_string(), age: 30, email: None },
        User { id: 3, name: "Charlie".to_string(), age: 35, email: None },
    ]).await?;
    
    // 2. Query data
    let all_users: Vec<User> = db.select::<User>().collect().await?;
    println!("All users: {:?}", all_users);
    
    // 3. Update data
    db.update::<User>()
        .filter(|u| u.id.eq(1))
        .set(|u| u.age, 26)
        .execute()
        .await?;
    
    // 4. Delete data
    db.delete::<User>()
        .filter(|u| u.id.eq(3))
        .execute()
        .await?;
    
    // 5. Cleanup
    db.drop_table::<User>().await?;
    
    Ok(())
}

Best Practices

1. Batch Operations Over Loops

// ✅ Recommended: Batch insert
db.insert(&users).await?;

// ❌ Avoid: Loop insert
for user in &users {
    db.insert(user).await?;  // Slow!
}

2. Use Transactions for Consistency

let mut txn = db.begin().await?;

txn.insert(&user1).await?;
txn.insert(&user2).await?;

txn.commit().await?;

3. Set Filter Conditions Properly

// ✅ Explicitly specify conditions
db.delete::<User>()
    .filter(|u| u.id.eq(1))
    .execute()
    .await?;

// ❌ Dangerous: Forgot filter condition
db.delete::<User>().execute().await?;  // Deletes all!

4. Check Operation Results

let count = db.update::<User>()
    .filter(|u| u.id.eq(1))
    .set(|u| u.name, "New Name".to_string())
    .execute()
    .await?;

if count == 0 {
    println!("No rows updated");
}
Prev
Database Connection
Next
Query Builder