Parfois, ActiveRecord ne suffit pas. Tu as peut-être besoin d’une requête complexe avec plusieurs jointures, ou tu veux tirer le maximum de performances de ta base de données. C’est là que le SQL brut devient utile.
Voici tout ce que tu dois savoir pour exécuter du SQL brut dans Rails, des bases jusqu’aux pièges courants à éviter.
Quand as-tu vraiment besoin de SQL brut ?
La plupart du temps, ActiveRecord fait très bien l’affaire. Mais voici les cas concrets où le SQL brut a du sens :
- Agrégations complexes - quand tu as besoin de fonctions de fenêtrage, de CTE ou d’opérations GROUP BY complexes
- Requêtes critiques pour les performances - quand le SQL généré par ActiveRecord est inefficace
- Fonctionnalités propres à une base de données - opérateurs JSONB de PostgreSQL, recherche FULLTEXT de MySQL, etc.
- Opérations en masse - mises à jour massives qui seraient lentes avec des appels ActiveRecord individuels
Passons à la pratique.
Un exemple concret : les statistiques utilisateurs
Imaginons que tu crées des statistiques utilisateurs et que tu doives trouver les utilisateurs inscrits ces 7 derniers jours, avec leur nombre de posts. Voici à quoi ça ressemble :
Trois façons d’exécuter du SQL brut
Rails te propose plusieurs options pour exécuter du SQL brut. Voici les principales :
1. connection.execute - pour des résultats bruts
Utilise-la quand tu veux les résultats bruts de la base de données :
sql = <<~SQL
SELECT
u.id, u.name, u.email,
COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON p.user_id = u.id
WHERE u.created_at >= NOW() - INTERVAL '7 days'
GROUP BY u.id, u.name, u.email
ORDER BY post_count DESC
SQL
result = ActiveRecord::Base.connection.execute(sql)
result.each do |row|
puts "#{row['name']}: #{row['post_count']} posts"
end
2. find_by_sql - pour des objets modèles
Quand tu veux récupérer de vrais objets ActiveRecord :
users = User.find_by_sql([
"SELECT * FROM users WHERE created_at >= ? AND status = ?",
7.days.ago, 'active'
])
users.each { |user| puts user.email }
3. pluck avec Arel - l’approche hybride
Pour les cas simples, tu peux quand même utiliser un peu de SQL brut avec ActiveRecord :
User.where("created_at >= ?", 7.days.ago)
.pluck("name, email, DATE(created_at) as signup_date")
Ne te fais pas pirater : prévenir l’injection SQL
C’est crucial : n’interpole jamais les saisies utilisateur directement dans des chaînes SQL. Voici ce qu’il ne faut pas faire :
# DON'T DO THIS - vulnerable to SQL injection
email = params[:email]
User.find_by_sql("SELECT * FROM users WHERE email = '#{email}'")
Utilise plutôt des requêtes paramétrées :
# Safe approach with parameters
email = params[:email]
User.find_by_sql(["SELECT * FROM users WHERE email = ?", email])
# Or use connection.quote for raw execute
email = params[:email]
sanitized_email = ActiveRecord::Base.connection.quote(email)
result = ActiveRecord::Base.connection.execute("SELECT * FROM users WHERE email = #{sanitized_email}")
Les paramètres sont automatiquement échappés et sécurisés. Utilise-les toujours.
Conseils de performance
Le SQL brut est souvent une question de performances, alors voici quelques conseils de pro :
Utilise Beekeeper Studio pour analyser tes requêtes - c’est parfait pour tester et optimiser ton SQL avant de l’intégrer à ton app Rails.
Ajoute des index sur les colonnes que tu filtres ou sur lesquelles tu fais des jointures :
# In a migration
add_index :users, :created_at
add_index :posts, [:user_id, :status]
Utilise EXPLAIN pour comprendre les performances d’une requête :
ActiveRecord::Base.connection.execute("EXPLAIN ANALYZE #{your_sql}")
Pense aux vues pour les requêtes complexes et réutilisables, plutôt que de répéter du SQL brut partout.
En résumé
Le SQL brut dans Rails, c’est comme un couteau bien aiguisé : puissant quand tu en as besoin, mais à manier avec précaution. Utilise-le pour les requêtes complexes, l’optimisation des performances et les fonctionnalités propres à ta base de données qu’ActiveRecord ne gère pas.
À retenir :
- Utilise toujours des requêtes paramétrées pour éviter l’injection SQL
- Teste d’abord tes requêtes avec un outil comme Beekeeper Studio
- N’abandonne pas complètement ActiveRecord : utilise le SQL brut de façon stratégique
Pour aller plus loin
- Rails Guides : Active Record Query Interface
- Conseils de performance PostgreSQL
- Optimisation des requêtes MySQL
- Essaie Beekeeper Studio pour développer en SQL - c’est la meilleure façon d’écrire et de tester des requêtes SQL
Des questions sur la gestion de bases de données ou l’optimisation SQL ? Beekeeper Studio te permet d’explorer facilement tes données et de peaufiner tes requêtes avant de les déployer.
Beekeeper Studio est une interface de base de données gratuite & open source
Le meilleur outil de requêtes & éditeur SQL que j’aie jamais utilisé. Il m’offre tout ce dont j’ai besoin pour gérer ma base de données. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio est rapide, intuitif et facile à utiliser. Beekeeper prend en charge plein de bases de données et fonctionne parfaitement sous Windows, Mac et Linux.
Ce que les utilisateurs disent de Beekeeper Studio
« Beekeeper Studio a complètement remplacé mon ancien workflow SQL. C’est rapide, intuitif, et ça rend le travail sur les bases de données à nouveau agréable. »
« J’ai essayé beaucoup d’interfaces de bases de données, mais Beekeeper trouve l’équilibre parfait entre fonctionnalités et simplicité. Ça marche, tout simplement. »