SQLAlchemy: evitar el cierre automático

Necesito insert / actualizar filas masivas a través de SQLAlchemy. Y get filas insertadas.

Intenté hacerlo con session.execute:

>>> posts = db.session.execute(Post.__table__.insert(), [{'title': 'dfghdfg', 'content': 'sdfgsdf', 'topic': topic}]*2) >>> posts.fetchall() ResourceClosedError Traceback (most recent call last) 

Y con motor:

 In [17]: conn = db.engine.connect() In [18]: result = conn.execute(Post.__table__.insert(), [{'title': 'title', 'content': 'content', 'topic': topic}]*2) In [19]: print result.fetchall() ResourceClosedError: This result object does not return rows. It has been closed automatically. 

La misma respuesta es que un object se ha cerrado automáticamente. ¿Cómo prevenirlo?

Primera respuesta – sobre "prevenir el cierre automático".

SQLAlchemy ejecuta DBAPI execute () o executemany () con insert y no hace ninguna consulta de selección. Entonces la exception que tienes es el comportamiento esperado. El object ResultProxy que se devuelve después de la ejecución de la consulta ejecutada ajusta el cursor DB-API que no permite hacer .fetchall() en él. Una vez que .fetchall() falla, ResultProxy le devuelve al usuario la exception de su sierra.

La única información que puede get después de la operación de inserción / actualización / eliminación sería el número de filas afectadas o el valor de la key principal después del incremento automático (según la database y el controller de la database).

Si su objective es recibir esta información amable, considere verificar los methods y attributes de ResultProxy como:

  • .inserted_primary_key
  • .last_inserted_params ()
  • .lastrowid
  • etc

Segunda respuesta: sobre "cómo hacer la inserción / actualización masiva y get las filas resultantes".

No hay forma de cargar filas insertadas mientras se hace una consulta de inserción única usando DBAPI. La API SQLAlchemy SQL Expression que está utilizando para realizar inserciones / actualizaciones masivas tampoco proporciona dicha funcionalidad. SQLAlchemy ejecuta DBAPI executemany () y se basa en la implementación del controller. Vea esta sección de documentation para más detalles.

La solución sería diseñar su tabla de manera que cada logging tenga una key natural para identificar loggings (combinación de valores de columnas que identifiquen el logging de manera única). Así que insert / actualizar / seleccionar consultas podría apuntar a un logging. Después de hacerlo, sería posible hacer primero la inserción / actualización masiva y luego hacer una consulta select por key natual. Por lo tanto, no necesitará saber el valor de key primaria autoincrementado.

Otra opción: puede ser que usted pueda usar SQLAlchemy Object Relational API para crear objects, entonces SQLAlchemy puede tratar de optimizar la inserción para hacer una consulta con executemany para usted. Me funcionó al usar Oracle DB. No habrá ninguna optimization para actualizaciones desde el primer momento. Verifique esta pregunta SO para get ideas eficientes de actualización masiva