0Pricing
Learn Rust Coding · Lektion

Datenbankintegration (SQLx/Diesel)

Integrieren Sie Ihren Rust-Webdienst mithilfe gängiger ORMs oder Query Builder wie SQLx oder Diesel in Datenbanken.

Datenbankintegration (SQLx/Diesel) ist eine kostenlose Learn Rust Coding-Lektion auf CoddyKit. Dies ist Lektion 2 von 3. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Learn Rust Coding-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Learn Rust Coding-Kurs umfasst insgesamt 3 Lektionen.

Warum Datenbanken für das Web?

Webdienste müssen Daten häufig dauerhaft speichern und abrufen. Denken Sie an Benutzerprofile, Produktkataloge oder Blogbeiträge – diese Daten müssen außerhalb des Speichers Ihres Programms gespeichert werden.

Datenbanken bieten eine strukturierte Möglichkeit, diese Daten zu verwalten, und stellen sicher, dass sie geschützt, konsistent und zugänglich sind. Die Anbindung Ihres Rust-Webdienstes an eine Datenbank gehört zu den zentralen Aufgaben der meisten Anwendungen aus der Praxis.

SQLx: Ihr asynchroner Datenbankhelfer

In Rust stehen uns hervorragende Werkzeuge für die Datenbankinteraktion zur Verfügung. Zwei beliebte Optionen sind SQLx und Diesel.

  • SQLx: Ein asynchrones, vollständig in Rust geschriebenes SQL-Crate mit zur Compile-Zeit geprüften Abfragen. Es wird häufig für asynchrone Webdienste mit Frameworks wie Tokio bevorzugt.
  • Diesel: Ein leistungsfähiges ORM (Object-Relational Mapper), das eine abstraktere Interaktion mit Ihrer Datenbank ermöglicht und Rust-Structs direkt auf Datenbanktabellen abbildet. Es arbeitet typischerweise synchron.

In dieser Lektion konzentrieren wir uns aufgrund der starken Unterstützung für asynchrone Verarbeitung auf SQLx, da diese gut zur modernen Entwicklung von Rust-Webdiensten passt.

SQLx einrichten: Abhängigkeiten

Bevor Sie Code schreiben, müssen Sie sqlx und tokio zur Cargo.toml Ihres Projekts hinzufügen. tokio stellt die von sqlx benötigte asynchrone Laufzeitumgebung bereit.

Wenn Sie beispielsweise SQLite (eine einfache dateibasierte Datenbank für die lokale Entwicklung) mit SQLx verwenden möchten, könnte Ihre Cargo.toml so aussehen:

[dependencies] sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "sqlite"] } tokio = { version = "1", features = ["full"] }

Üblicherweise verwenden Sie außerdem eine Umgebungsvariable DATABASE_URL, um die Verbindungszeichenfolge Ihrer Datenbank zu konfigurieren.

Mit Ihrer ersten Datenbank verbinden

Stellen wir eine Verbindung zu einer im Speicher befindlichen SQLite-Datenbank her. SQLx verwendet Verbindungspools, die mehrere Datenbankverbindungen effizient verwalten, um gleichzeitige Anfragen in Ihrem Webdienst zu verarbeiten.

Führen Sie dieses Beispiel aus:

use sqlx::SqlitePool;
use tokio;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    // Use an in-memory SQLite database for simplicity
    let database_url = "sqlite::memory:"; 
    let pool = SqlitePool::connect(&database_url).await?;
    println!("Successfully connected to the database!");

    // In a real web app, 'pool' would be passed around or stored in app state.

    Ok(())
}

Daten mit Tabellen strukturieren

Bevor wir Daten speichern können, müssen wir unser Datenbankschema mithilfe von DDL (Data Definition Language) definieren. Erstellen wir eine einfache Tabelle tasks.

Mit dem Makro sqlx::query! können Sie SQL direkt in Ihren Rust-Code einbetten. Es führt sogar Prüfungen Ihres SQL-Codes zur Compile-Zeit durch!

use sqlx::{SqlitePool, query};
use tokio;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let database_url = "sqlite::memory:";
    let pool = SqlitePool::connect(&database_url).await?;

    // Create a 'tasks' table if it doesn't exist
    query!(
        "CREATE TABLE IF NOT EXISTS tasks (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            description TEXT NOT NULL,
            completed BOOLEAN NOT NULL DEFAULT FALSE
        )"
    ).execute(&pool).await?;

    println!("Table 'tasks' created successfully!");
    Ok(())
}

Neue Datensätze hinzufügen

Da wir nun eine Tabelle haben, fügen wir einige Daten hinzu! Wir verwenden die Anweisung INSERT mit Parameterbindung. Das schützt vor SQL-Injection und macht Ihre Abfragen sicherer.

Beachten Sie, dass die Platzhalter ? für Parameter verwendet und die Werte an .bind() übergeben werden.

use sqlx::{SqlitePool, query};
use tokio;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let database_url = "sqlite::memory:";
    let pool = SqlitePool::connect(&database_url).await?;

    query!(
        "CREATE TABLE IF NOT EXISTS tasks (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            description TEXT NOT NULL,
            completed BOOLEAN NOT NULL DEFAULT FALSE
        )"
    ).execute(&pool).await?;

    // Insert a new task
    let description = "Learn SQLx";
    let completed = false;
    query!(
        "INSERT INTO tasks (description, completed) VALUES (?, ?)",
        description,
        completed
    ).execute(&pool).await?;

    println!("Task '{}' inserted successfully!", description);
    Ok(())
}

Daten mit SELECT abrufen

Um Daten aus unserer Tabelle tasks abzurufen, verwenden wir die Anweisung SELECT. SQLx stellt Methoden wie .fetch_all() oder .fetch_one() bereit, um Ergebnisse abzurufen.

Sie können die zurückgegebenen Zeilen durchlaufen und über den Namen oder den Index auf Spalten zugreifen.

use sqlx::{SqlitePool, query};
use tokio;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let database_url = "sqlite::memory:";
    let pool = SqlitePool::connect(&database_url).await?;

    query!(
        "CREATE TABLE IF NOT EXISTS tasks (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            description TEXT NOT NULL,
            completed BOOLEAN NOT NULL DEFAULT FALSE
        )"
    ).execute(&pool).await?;

    query!(
        "INSERT INTO tasks (description, completed) VALUES (?, ?)",
        "Learn SQLx", false
    ).execute(&pool).await?;
    query!(
        "INSERT INTO tasks (description, completed) VALUES (?, ?)",
        "Build a web app", false
    ).execute(&pool).await?;

    // Fetch and print all tasks
    println!("\n--- All Tasks ---");
    let rows = query!("SELECT id, description, completed FROM tasks")
        .fetch_all(&pool).await?;

    for row in rows {
        println!("ID: {}, Desc: {}, Done: {}", 
            row.id, row.description, row.completed);
    }
    Ok(())
}

Typsichere Daten mit Structs

Das manuelle Extrahieren von Daten aus Zeilen kann fehleranfällig sein. Mit dem SQLx-Makro query_as! können Sie zusammen mit #[derive(FromRow)] Abfrageergebnisse direkt auf Rust-Structs abbilden!

Das sorgt für eine starke Typsicherheit und macht Ihren Code deutlich übersichtlicher und einfacher zu bearbeiten.

use sqlx::{FromRow, SqlitePool, query, query_as};
use tokio;

#[derive(Debug, FromRow)]
struct Task {
    id: i64,
    description: String,
    completed: bool,
}

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let database_url = "sqlite::memory:";
    let pool = SqlitePool::connect(&database_url).await?;

    query!(
        "CREATE TABLE IF NOT EXISTS tasks (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            description TEXT NOT NULL,
            completed BOOLEAN NOT NULL DEFAULT FALSE
        )"
    ).execute(&pool).await?;

    query!(
        "INSERT INTO tasks (description, completed) VALUES (?, ?)",
        "Learn SQLx", false
    ).execute(&pool).await?;

    // Fetch tasks directly into our Task struct
    println!("\n--- Tasks as Structs ---");
    let tasks = query_as::<_, Task>("SELECT id, description, completed FROM tasks")
        .fetch_all(&pool).await?;

    for task in tasks {
        println!("{:?}", task);
    }
    Ok(())
}

Datensätze ändern und löschen

Das Aktualisieren und Löschen von Daten folgt einem ähnlichen Muster wie das Einfügen. Sie verwenden die SQL-Anweisungen UPDATE und DELETE mit Parameterbindung.

  • UPDATE: Ändert vorhandene Zeilen auf Grundlage einer WHERE-Klausel.
  • DELETE: Entfernt Zeilen auf Grundlage einer WHERE-Klausel.

Seien Sie bei WHERE-Klauseln in UPDATE und DELETE stets vorsichtig, um unbeabsichtigten Datenverlust zu vermeiden!

use sqlx::{SqlitePool, query};
use tokio;

#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
    let database_url = "sqlite::memory:";
    let pool = SqlitePool::connect(&database_url).await?;

    query!(
        "CREATE TABLE IF NOT EXISTS tasks (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            description TEXT NOT NULL,
            completed BOOLEAN NOT NULL DEFAULT FALSE
        )"
    ).execute(&pool).await?;

    query!(
        "INSERT INTO tasks (description, completed) VALUES (?, ?)",
        "Finish lesson", false
    ).execute(&pool).await?;
    let task_id_to_update = 1;

    // Update a task
    query!(
        "UPDATE tasks SET completed = ? WHERE id = ?",
        true,
        task_id_to_update
    ).execute(&pool).await?;
    println!("Task {} updated.", task_id_to_update);

    // Delete a task (uncomment to run, careful with IDs after update)
    // let task_id_to_delete = 1;
    // query!(
    //     "DELETE FROM tasks WHERE id = ?",
    //     task_id_to_delete
    // ).execute(&pool).await?;
    // println!("Task {} deleted.", task_id_to_delete);

    Ok(())
}

Testen Sie Ihre Datenbankkenntnisse

Welche der folgenden Aussagen über SQLx in Rust-Webdiensten sind RICHTIG?

Datenbankanbindung: Die wichtigsten Erkenntnisse

Mit dem Erlernen der Datenbankanbindung haben Sie einen wichtigen Schritt beim Aufbau robuster Rust-Webdienste gemacht!

  • Persistenz: Datenbanken sind für das Speichern von Anwendungsdaten unverzichtbar.
  • SQLx: Ein asynchrones, zur Compile-Zeit geprüftes SQL-Crate, das sich hervorragend für Webdienste eignet.
  • Verbindungspools: Unverzichtbar für einen effizienten und nebenläufigen Datenbankzugriff.
  • CRUD: Wir haben das Erstellen (INSERT), Abrufen (SELECT), Aktualisieren (UPDATE) und Löschen (DELETE) von Daten behandelt.
  • Typsicherheit: query_as! und #[derive(FromRow)] ermöglichen eine sichere und ergonomische Datenzuordnung.

Als Nächstes können Sie untersuchen, wie sich diese Datenbankoperationen in echte Webrouten integrieren lassen!

Häufig gestellte Fragen

Ist die Lektion „Datenbankintegration (SQLx/Diesel)“ kostenlos?

Ja — der vollständige Text von „Datenbankintegration (SQLx/Diesel)“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Learn Rust Coding-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Learn Rust Coding-Kurs umfasst insgesamt 3 Lektionen.

Was lerne ich in „Datenbankintegration (SQLx/Diesel)“?

Integrieren Sie Ihren Rust-Webdienst mithilfe gängiger ORMs oder Query Builder wie SQLx oder Diesel in Datenbanken. Du übst Learn Rust Coding mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Learn Rust Coding zu starten?

Keine Vorkenntnisse erforderlich. Learn Rust Coding auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 3.

Wie lange dauert die Lektion „Datenbankintegration (SQLx/Diesel)“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Learn Rust Coding-Lektion Code schreiben und ausführen?

Ja. Jede Learn Rust Coding-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. REST-APIs mit Actix-web/Rocket
  2. Datenbankintegration (SQLx/Diesel)
  3. Authentifizierung und Autorisierung
← Zurück zu Learn Rust Coding