Cómo Ejecutar SQL en Bruto en SQLAlchemy
Published on
En el mundo de la ciencia de datos y el desarrollo web, el uso de bases de datos es inevitable. Estos poderosos sistemas contienen y gestionan porciones significativas de datos, haciéndolos invaluables en un mundo que depende fuertemente de la información. Python, un lenguaje de programación prominente en estos dominios, aprovecha varias herramientas para comunicarse con bases de datos, y una de estas herramientas es SQLAlchemy. Si bien la capa de mapeo objeto-relacional (ORM) de SQLAlchemy es una bendición para los desarrolladores que buscan abstracciones de alto nivel para sus operaciones de base de datos, hay ocasiones en las que ejecutar consultas SQL en bruto es más efectivo o intuitivo. Este artículo ofrece una inmersión profunda en la ejecución de consultas SQL en bruto dentro de SQLAlchemy, proporcionando ejemplos de código concretos para claridad y comprensión.
Comprendiendo SQLAlchemy: Una Descripción General
Para comprender el concepto de ejecutar SQL en bruto en SQLAlchemy, primero necesitamos comprender qué es SQLAlchemy. Como un conjunto de herramientas SQL, SQLAlchemy proporciona una serie de herramientas para que las aplicaciones de Python interactúen con bases de datos SQL. Ofrece una suite completa de patrones de persistencia de nivel empresarial bien conocidos, diseñados para un acceso a la base de datos eficiente y de alto rendimiento.
SQLAlchemy tiene como objetivo acomodar tanto operaciones de base de datos de alto como bajo nivel. Sus dos componentes principales, SQLAlchemy Core y SQLAlchemy ORM, manejan estas operaciones. SQLAlchemy Core se centra en la abstracción de SQL, metadatos de esquema, agrupamiento de conexiones, coerción de tipos y más. Proporciona una interfaz SQL de bajo nivel para Python, lo que permite a los desarrolladores interactuar con la base de datos de una manera Pythonica. Por otro lado, SQLAlchemy ORM es una API de alto nivel y centrada en los datos que proporciona patrones de modelo de dominio, encapsulando bases de datos y tablas como clases y objetos de Python.
El Poder y Potencial de SQL en Bruto
Con el trasfondo de SQLAlchemy y sus componentes, centrémonos ahora en las consultas SQL en bruto. SQL en bruto se refiere a declaraciones y consultas SQL escritas como simples cadenas de texto plano. Como lenguaje de base de datos, SQL (Structured Query Language) nos permite acceder y manipular bases de datos. Las consultas SQL en bruto se utilizan a menudo cuando hay una necesidad de ejecutar operaciones complejas en las que la abstracción ORM puede parecer restrictiva.
Estas consultas SQL en bruto son excepcionalmente útiles cuando resulta difícil expresar una operación de base de datos en la capa ORM o cuando la sintaxis ORM es menos intuitiva que la operación SQL equivalente. Además, los desarrolladores que se sienten más cómodos escribiendo consultas SQL pueden encontrar en SQL en bruto en SQLAlchemy una excelente manera de obtener lo mejor de ambos mundos: el poder de SQL con la comodidad de Python.
Cómo Ejecutar SQL en Bruto en SQLAlchemy
En SQLAlchemy, SQL en bruto puede ser ejecutado directamente utilizando el método execute()
ofrecido por los objetos Engine
y Session
.
Utilizando el Método Execute del Motor
Veamos un ejemplo de ejecución de SQL en bruto utilizando el método engine.execute()
:
from sqlalchemy import create_engine
engine = create_engine('sqlite:///:memory:')
result = engine.execute("SELECT * FROM users WHERE age >= :age", {'age': 21})
for row in result:
print(row)
En el código anterior, estamos ejecutando una consulta SQL en bruto que busca todos los usuarios de 21 años o más. La función create_engine()
establece una conexión con la base de datos (en este caso, una base de datos SQLite en memoria). El método execute()
en la instancia del motor luego toma la consulta SQL como una cadena y la ejecuta en la base de datos.
Utilizando el Método Execute del Session
Como alternativa, SQL en bruto también se puede ejecutar utilizando el método session.execute()
:
from sqlalchemy.orm import Session
sesión = Session(bind=engine)
result = session.execute("SELECT * FROM users WHERE age >= :age", {'age': 21})
for row in result:
print(row)
```Este ejemplo parece bastante similar al anterior. Sin embargo, hay una distinción sutil pero crucial. El método `session.execute()` asegura que las consultas son administradas por una transacción. En la terminología de las bases de datos, una transacción es una secuencia de operaciones realizadas como una única unidad lógica de trabajo. Por lo tanto, la sesión permite que varias consultas en la misma solicitud sean confirmadas o desestimadas juntas, evitando inconsistencias y mejorando la confiabilidad del sistema. Por el contrario, el uso de `engine.execute()` puede dejar el sistema más propenso a errores que podrían llevar a la corrupción de datos.
import BlogSuggestion from '../../components/blog-suggestion';
<BlogSuggestion />
## El arte de comprometer transacciones
Al ejecutar consultas SQL crudas, es esencial comprender el proceso de confirmación de transacciones. Esto se vuelve significativo, especialmente cuando se realizan operaciones que modifican los datos, como `INSERT`, `UPDATE` o `DELETE`. SQLAlchemy, a través de su administración de sesión, permite el control sobre cuándo estos cambios deben hacerse permanentes.
Aquí hay un ejemplo:
```python
from sqlalchemy import text
con la sesión.comenzar():
sesión.execute(
texto("UPDATE usuarios SET edad =: nueva_edad WHERE edad =: vieja_edad"),
{'new_age': 30, 'old_age': 20}
)
En el código anterior, primero comenzamos una nueva transacción usando session.begin()
. Esta transacción incluye la consulta SQL cruda que actualiza la edad de todos los usuarios de 20 a 30. La transacción se confirma automáticamente al final del bloque with
. En caso de que ocurra una excepción durante la ejecución de la consulta, la transacción se deshace, manteniendo el estado de la base de datos consistente.
El papel vital de la parametrización
Vale la pena señalar que las consultas SQL crudas a veces pueden ser vulnerables a ataques de inyección SQL, una vulnerabilidad común de seguridad web. La parametrización es una técnica para prevenir tales ataques. La función text()
de SQLAlchemy ayuda a parametrizar consultas SQL crudas.
Aquí hay un ejemplo ilustrativo:
from sqlalchemy import text
consulta = texto("SELECT * FROM usuarios WHERE nombre =: nombre")
resultado = sesión.execute(consulta, {'name': 'Alice'})
En el fragmento de código anterior, el :nombre
dentro de la cadena de consulta es un parámetro de enlace. Cuando se llama a la función execute()
, pasamos un diccionario que asigna estos parámetros a sus valores respectivos. Esta característica asegura que los datos se escapen correctamente, mitigando el riesgo de inyección SQL.
Dominar las vistas e incorporaciones en línea
Las consultas complejas a menudo requieren el uso de vistas e incorporaciones en línea. Las vistas en línea son subconsultas en la cláusula FROM
, lo que nos permite usar el resultado de una consulta como una tabla. Las incorporaciones, por otro lado, combinan filas de dos o más tablas en función de columnas relacionadas. Aquí hay un ejemplo de SQL crudo con una vista en línea y una incorporación:
consulta = texto("""
SELECT usuarios.nombre, recuentos.count_invoice
DE usuarios
ÚNETE (SELECT id_de_usuario, COUNT(*) AS count_invoice FROM facturas GROUP BY id_de_usuario) como recuentos
EN usuarios.id = recuentos.id_de_usuario
DONDE recuentos.count_invoice >: count
""")
resultado = sesión.execute(consulta, {'count': 10})
Esta consulta recupera todos los usuarios que tienen más de 10 facturas. La vista en línea aquí es la tabla counts
, que es el resultado de la subconsulta que calcula el número de facturas para cada usuario.
Conclusión
La capacidad de ejecutar SQL en bruto en SQLAlchemy proporciona la flexibilidad para tratar con consultas complejas mientras se preserva la facilidad y seguridad de usar un lenguaje de alto nivel como Python. Este enfoque combina las capacidades completas de SQL con la usabilidad de Python, dándole a los desarrolladores la ventaja de crear operaciones de base de datos eficientes, intuitivas y seguras.
Preguntas frecuentes
P1: ¿Cómo puedo ejecutar una consulta de SQL en bruto en SQLAlchemy?
Puede usar tanto el método session.execute()
como engine.execute()
para ejecutar consultas de SQL en bruto en SQLAlchemy. Se recomienda utilizar el método session.execute()
ya que asegura que las consultas sean gestionadas correctamente por una transacción.
P2: ¿Cómo puedo hacer una consulta SELECT en SQLAlchemy?
Para hacer una consulta SELECT, pase la cadena de consulta de SQL en bruto al método execute()
. Por ejemplo, result = session.execute("SELECT * FROM users")
recuperará todas las filas de la tabla users
.
P3: ¿Cómo puedo evitar la inyección de SQL al usar consultas de SQL en bruto en SQLAlchemy?
Para evitar la inyección de SQL al usar consultas de SQL en bruto en SQLAlchemy, utilice la parametrización pasando los parámetros de la consulta como valores de vinculación para asegurar la escapación y validación adecuada de la entrada del usuario.