A veces ActiveRecord simplemente no es suficiente. Tal vez necesitas una consulta compleja con varios joins, o quieres exprimir hasta la última gota de rendimiento de tu base de datos. Ahí es cuando el SQL puro resulta muy útil.
Aquí tienes todo lo que necesitas saber para ejecutar SQL puro en Rails: desde lo básico hasta cómo evitar los errores más comunes.
Cuándo necesitas realmente SQL puro
La mayoría de las veces, ActiveRecord funciona perfecto. Pero estos son los casos reales en los que el SQL puro tiene sentido:
- Agregaciones complejas: cuando necesitas funciones de ventana, CTE u operaciones GROUP BY complejas
- Consultas críticas para el rendimiento: cuando el SQL que genera ActiveRecord es ineficiente
- Funciones específicas de la base de datos: usar los operadores JSONB de PostgreSQL, la búsqueda FULLTEXT de MySQL, etc.
- Operaciones masivas: actualizaciones en lote que serían lentas con llamadas individuales de ActiveRecord
Vamos a lo práctico.
Un ejemplo real: analíticas de usuarios
Digamos que estás creando analíticas de usuarios y necesitas encontrar a los usuarios que se registraron en los últimos 7 días, junto con su número de publicaciones. Así se ve:
Tres formas de ejecutar SQL puro
Rails te da varias opciones para ejecutar SQL puro. Estas son las principales:
1. connection.execute: para resultados sin procesar
Úsalo cuando quieras los resultados tal cual vienen de la base de datos:
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: para objetos del modelo
Cuando quieres recibir objetos de ActiveRecord de verdad:
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 con Arel: el enfoque híbrido
Para casos sencillos, puedes usar algo de SQL puro junto con ActiveRecord:
User.where("created_at >= ?", 7.days.ago)
.pluck("name, email, DATE(created_at) as signup_date")
Que no te hackeen: cómo prevenir la inyección SQL
Esto es fundamental: nunca interpoles la entrada del usuario directamente en cadenas SQL. Esta es la forma incorrecta:
# DON'T DO THIS - vulnerable to SQL injection
email = params[:email]
User.find_by_sql("SELECT * FROM users WHERE email = '#{email}'")
En su lugar, usa consultas parametrizadas:
# 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}")
Los parámetros se escapan automáticamente y son seguros. Úsalos siempre.
Consejos de rendimiento
El SQL puro suele tener que ver con el rendimiento, así que aquí van algunos consejos pro:
Usa Beekeeper Studio para analizar tus consultas: es perfecto para probar y optimizar SQL antes de meterlo en tu app de Rails.
Agrega índices en las columnas por las que filtras o haces joins:
# In a migration
add_index :users, :created_at
add_index :posts, [:user_id, :status]
Usa EXPLAIN para entender el rendimiento de tus consultas:
ActiveRecord::Base.connection.execute("EXPLAIN ANALYZE #{your_sql}")
Considera usar vistas de base de datos para consultas complejas y reutilizables en lugar de repetir SQL puro por todos lados.
Para cerrar
El SQL puro en Rails es como un cuchillo afilado: poderoso cuando lo necesitas, pero hay que manejarlo con cuidado. Úsalo para consultas complejas, optimización de rendimiento y funciones específicas de la base de datos que ActiveRecord no puede manejar.
Recuerda:
- Usa siempre consultas parametrizadas para prevenir la inyección SQL
- Prueba primero tus consultas con una herramienta como Beekeeper Studio
- No abandones ActiveRecord por completo: usa SQL puro de forma estratégica
Lecturas recomendadas
- Rails Guides: Active Record Query Interface
- Consejos de rendimiento para PostgreSQL
- Optimización de consultas en MySQL
- Prueba Beekeeper Studio para desarrollar en SQL: es la mejor forma de escribir y probar consultas SQL
¿Tienes dudas sobre administración de bases de datos u optimización de SQL? Beekeeper Studio te facilita explorar tus datos y perfeccionar tus consultas antes de desplegarlas.
Beekeeper Studio es un cliente de bases de datos gratuito y de código abierto
La mejor herramienta de consultas y edición de SQL que he usado. Tiene todo lo que necesito para administrar mi base de datos. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio es rápido, intuitivo y fácil de usar. Es compatible con muchísimas bases de datos y funciona de maravilla en Windows, Mac y Linux.
Lo que dicen los usuarios de Beekeeper Studio
"Beekeeper Studio reemplazó por completo mi antiguo flujo de trabajo con SQL. Es rápido, intuitivo y hace que trabajar con bases de datos vuelva a ser agradable."
"He probado muchas GUI de bases de datos, pero Beekeeper logra el equilibrio perfecto entre funciones y sencillez. Simplemente funciona."