Después de consultar con expertos en este tema, programadores de deferentes áreas y profesores hemos dado con la solución al dilema y la plasmamos en este post.
Solución:
Le sugiero que haga ambos tutoriales antes de continuar su viaje con SQLAlchemy. Son realmente útiles y explican muchos conceptos. Después, le sugiero que lea Uso de la sesión, ya que esto continúa explicando cómo encaja la sesión en todo esto.
Para su problema, hay dos soluciones: una usando el ORM y la otra usando el Core. El primero es más fácil, el segundo es más rápido. Tomemos primero el camino fácil. Una transacción solo se usa para envolver todas sus declaraciones en una sola operación. Es decir, si algo falla, puede abortar todo y no quedarse con algo intermedio. Por lo tanto, lo más probable es que desee una transacción, pero funcionaría sin ella. Esta es la forma más rápida:
with session.begin():
session.add_all([tableRow(row) for row in listOfRows])
Dependiendo de sus datos, SQLAlchemy podría incluso optimizar su INSERT
declaración de tal manera que se ejecuta múltiples a la vez. Esto es lo que está pasando:
- Se inicia una transacción utilizando
session.begin
- Los datos se agregan (usando
add_all
sino un bucle con múltiplesadd
también estaría bien) - La sesión está comprometida. Si algo sale mal aquí, la transacción se cancelará y podrá corregir el error.
Entonces, esta es claramente una buena manera, pero no es la manera más rápida, porque SQLAlchemy tiene que pasar por todos los algoritmos ORM que pueden producir una sobrecarga. Si se trata de una inicialización única de la base de datos, puede evitar el ORM. En ese caso, en lugar de crear una clase ORM (tableRow
), se crea un diccionario con todos keys (cómo depende de los datos). Nuevamente puedes usar un administrador de contexto:
with engine.begin() as connection:
connection.execute(tableRow.__table__.insert().
values([row_to_dict(row) for row in listOfRows]))
Esto probablemente sería un poco más rápido pero también menos conveniente. Funciona de la misma manera que la sesión anterior, solo que construye la declaración desde el Núcleo y no desde el ORM.
ACTUALIZACIÓN 2020-01-23
la respuesta de @javex está desactualizada.
TLDR: puede usar la sesión directamente sin llamar begin
. Solo asegúrate autocommit
se establece en false
Respuesta larga:
Consulte la documentación de la sesión https://docs.sqlalchemy.org/en/13/orm/session_api.html
Advertencia
El método Session.begin() es parte de un patrón más amplio de uso con la sesión conocido como modo de confirmación automática. Este es esencialmente un modo de uso heredado y no es necesario para nuevas aplicaciones. La sesión normalmente maneja el trabajo de “comenzar” de manera transparente, que a su vez se basa en Python DBAPI para “comenzar” las transacciones de manera transparente; no hay necesidad de comenzar explícitamente las transacciones cuando se utilizan patrones de programación de sesión modernos. En su modo predeterminado de autocommit=False, la sesión hace todo su trabajo dentro del contexto de una transacción, por lo que tan pronto como llama a Session.commit(), la siguiente transacción se inicia implícitamente cuando se invoca la siguiente operación de la base de datos. Consulte Modo de confirmación automática para obtener más información.