Rust et SQLx en 2026 : Requêtes Vérifiées à la Compilation et Questions d'Entretien
Guide complet sur SQLx avec Rust : requêtes SQL vérifiées à la compilation, comparaison avec les ORM, et questions techniques pour entretiens d'embauche.

SQLx représente une approche révolutionnaire de l'interaction avec les bases de données en Rust. Contrairement aux ORM traditionnels, SQLx vérifie les requêtes SQL directement à la compilation, éliminant une catégorie entière d'erreurs avant même l'exécution du programme. Cette caractéristique unique en fait un outil privilégié pour les applications critiques où la fiabilité de la couche données est primordiale.
En 2026, SQLx s'est imposé comme la solution de référence pour les développeurs Rust travaillant avec PostgreSQL, MySQL, et SQLite. Son adoption croissante dans l'industrie signifie que les questions relatives à SQLx apparaissent de plus en plus fréquemment lors des entretiens techniques pour des postes Rust.
SQLx utilise les macros procédurales de Rust pour analyser les requêtes SQL à la compilation. Cette vérification nécessite une connexion à la base de données pendant le build, mais garantit que chaque requête est syntaxiquement correcte et compatible avec le schéma.
Configuration Initiale de SQLx
L'installation de SQLx dans un projet Rust commence par l'ajout des dépendances appropriées. La configuration varie selon le moteur de base de données ciblé.
[dependencies]
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "macros", "chrono", "uuid"] }
tokio = { version = "1", features = ["full"] }
dotenvy = "0.15"La variable d'environnement DATABASE_URL doit être configurée pour permettre la vérification à la compilation :
export DATABASE_URL="postgres://user:password@localhost:5432/mydb"Requêtes avec Vérification à la Compilation
La macro sqlx::query! constitue le cœur de la fonctionnalité de vérification. Elle analyse la requête SQL, vérifie sa validité contre le schéma de la base, et génère du code Rust typé.
use sqlx::PgPool;
#[derive(Debug)]
struct User {
id: i32,
email: String,
created_at: chrono::DateTime<chrono::Utc>,
}
async fn get_user_by_id(pool: &PgPool, user_id: i32) -> Result<Option<User>, sqlx::Error> {
let row = sqlx::query!(
r#"
SELECT id, email, created_at
FROM users
WHERE id = $1
"#,
user_id
)
.fetch_optional(pool)
.await?;
Ok(row.map(|r| User {
id: r.id,
email: r.email,
created_at: r.created_at,
}))
}Si une colonne n'existe pas ou si le type ne correspond pas, le compilateur signale l'erreur immédiatement.
Utilisation de query_as pour le Mapping Automatique
Pour simplifier le mapping entre les résultats SQL et les structures Rust, query_as! offre une syntaxe plus concise :
use sqlx::FromRow;
#[derive(Debug, FromRow)]
struct Article {
id: i32,
title: String,
content: String,
author_id: i32,
published: bool,
}
async fn get_published_articles(pool: &PgPool) -> Result<Vec<Article>, sqlx::Error> {
sqlx::query_as!(
Article,
r#"
SELECT id, title, content, author_id, published
FROM articles
WHERE published = true
ORDER BY id DESC
LIMIT 50
"#
)
.fetch_all(pool)
.await
}Gestion des Transactions
Les transactions garantissent l'intégrité des opérations multiples. SQLx propose une API élégante pour les manipuler :
async fn transfer_funds(
pool: &PgPool,
from_account: i32,
to_account: i32,
amount: rust_decimal::Decimal,
) -> Result<(), sqlx::Error> {
let mut tx = pool.begin().await?;
sqlx::query!(
"UPDATE accounts SET balance = balance - $1 WHERE id = $2",
amount,
from_account
)
.execute(&mut *tx)
.await?;
sqlx::query!(
"UPDATE accounts SET balance = balance + $1 WHERE id = $2",
amount,
to_account
)
.execute(&mut *tx)
.await?;
tx.commit().await?;
Ok(())
}Mode Offline pour les Environnements CI/CD
Dans les pipelines de build où la base de données n'est pas accessible, SQLx supporte un mode offline. Les métadonnées des requêtes sont sauvegardées dans un fichier JSON :
cargo sqlx prepare --workspaceCette commande génère un fichier .sqlx/ contenant les informations de schéma nécessaires à la compilation sans connexion active.
// Avec SQLX_OFFLINE=true, la compilation utilise les métadonnées cachées
let users = sqlx::query_as!(User, "SELECT * FROM users WHERE active = true")
.fetch_all(&pool)
.await?;Comparaison avec Diesel et SeaORM
SQLx diffère fondamentalement des ORM comme Diesel ou SeaORM dans son approche :
// SQLx : SQL brut avec vérification
sqlx::query!("SELECT * FROM users WHERE email LIKE $1", pattern)
.fetch_all(&pool)
.await?;
// Diesel : DSL Rust compilé en SQL
users::table
.filter(users::email.like(pattern))
.load::<User>(&mut conn)?;
// SeaORM : API fluide avec modèles générés
User::find()
.filter(user::Column::Email.like(&pattern))
.all(&db)
.await?;SQLx privilégie le SQL natif, offrant un contrôle total sur les requêtes tout en maintenant la sécurité des types. Les ORM abstraient le SQL mais peuvent limiter l'accès aux fonctionnalités spécifiques de chaque moteur.
Gestion des Migrations
SQLx intègre un système de migration robuste :
sqlx migrate add create_users_tableCette commande crée un fichier de migration versionné :
-- migrations/20260912120000_create_users_table.sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_users_email ON users(email);L'application des migrations s'effectue programmatiquement ou via CLI :
sqlx::migrate!().run(&pool).await?;Pool de Connexions et Configuration
La configuration du pool de connexions impacte directement les performances :
use sqlx::postgres::PgPoolOptions;
use std::time::Duration;
async fn create_pool() -> Result<PgPool, sqlx::Error> {
PgPoolOptions::new()
.max_connections(20)
.min_connections(5)
.acquire_timeout(Duration::from_secs(3))
.idle_timeout(Duration::from_secs(600))
.max_lifetime(Duration::from_secs(1800))
.connect(&std::env::var("DATABASE_URL").unwrap())
.await
}Questions Techniques d'Entretien
Les entretiens techniques sur SQLx explorent plusieurs domaines clés.
Question : Comment SQLx vérifie-t-il les requêtes à la compilation ?
SQLx utilise les macros procédurales pour établir une connexion à la base de données pendant la compilation. La macro query! exécute une commande PREPARE pour valider la syntaxe et les types, puis génère du code Rust typé basé sur le schéma réel.
Question : Quelle est la différence entre query! et query_as! ?
La macro query! retourne un type anonyme avec des champs correspondant aux colonnes sélectionnées. query_as! mappe directement les résultats vers une structure définie, simplifiant le code quand la structure correspond exactement au résultat.
Question : Comment gérer les requêtes dynamiques avec SQLx ?
use sqlx::QueryBuilder;
async fn search_users(
pool: &PgPool,
name: Option<&str>,
email: Option<&str>,
) -> Result<Vec<User>, sqlx::Error> {
let mut builder: QueryBuilder<sqlx::Postgres> = QueryBuilder::new(
"SELECT id, email, created_at FROM users WHERE 1=1"
);
if let Some(n) = name {
builder.push(" AND name ILIKE ");
builder.push_bind(format!("%{}%", n));
}
if let Some(e) = email {
builder.push(" AND email = ");
builder.push_bind(e);
}
builder
.build_query_as::<User>()
.fetch_all(pool)
.await
}Question : Comment tester du code utilisant SQLx ?
L'approche recommandée utilise des transactions annulées pour isoler les tests :
#[sqlx::test]
async fn test_create_user(pool: PgPool) -> sqlx::Result<()> {
let user = create_user(&pool, "test@example.com").await?;
assert_eq!(user.email, "test@example.com");
Ok(())
// La transaction est automatiquement annulée
}Prêt à réussir tes entretiens Rust ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Bonnes Pratiques de Production
Plusieurs patterns optimisent l'utilisation de SQLx en production :
// Wrapper pour la gestion centralisée des erreurs
pub struct Database {
pool: PgPool,
}
impl Database {
pub async fn new() -> Result<Self, sqlx::Error> {
let pool = PgPoolOptions::new()
.max_connections(20)
.connect(&std::env::var("DATABASE_URL").unwrap())
.await?;
sqlx::migrate!().run(&pool).await?;
Ok(Self { pool })
}
pub fn pool(&self) -> &PgPool {
&self.pool
}
}L'encapsulation du pool dans une structure permet d'ajouter facilement des fonctionnalités comme le logging, les métriques, ou les retries.
Conclusion
SQLx établit un nouveau standard pour l'interaction avec les bases de données en Rust. Sa vérification à la compilation élimine les erreurs SQL à l'exécution tout en préservant la flexibilité du SQL natif. Pour les développeurs préparant des entretiens techniques, la maîtrise de SQLx démontre une compréhension approfondie de l'écosystème Rust et des principes de sécurité des types appliqués aux couches de données. La combinaison de performances optimales, de typage fort, et d'une API ergonomique fait de SQLx un choix judicieux pour les applications Rust modernes.
Tu saurais repérer le bug en Rust ?
Un vrai bout de code, un bug caché, une tentative par jour. Sans compte pour essayer.

Écrit par
Anthony Fillion-MailletFondateur de SharpSkill
Développeur fullstack depuis plus de 10 ans. Il dirige SharpSkill et répond de tout ce qui y est publié.
Mis à jour le 12 septembre 2026
Partager
Articles similaires

Thinkful vs Bloc pour Apprendre Rust en 2026 : Comparaison des Bootcamps et Guide d'Auto-formation
Comparaison complète des bootcamps Thinkful et Bloc pour apprendre la programmation Rust en 2026, incluant l'analyse des programmes, les tarifs, la qualité du mentorat et les alternatives d'auto-formation.

Apprendre Rust en 2026 : Comparatif des Bootcamps et Ressources d'Autoformation
Guide complet comparant les bootcamps Rust, les cours universitaires et les ressources gratuites pour apprendre Rust en 2026. Analyse des options Thinkful, Bloc et alternatives actuelles.

Les Lifetimes Rust Expliqués : Annotations, Élision et Questions d'Entretien 2026
Maîtriser les lifetimes Rust : annotations explicites, règles d'élision et préparation aux entretiens techniques avec des exemples pratiques.