Hasta donde yo sé, no hay forma de que el ORM emita inserciones en bloque. Creo que la razón subyacente es que SQLAlchemy necesita realizar un seguimiento de la identidad de cada objeto (es decir, nuevas claves primarias) y las inserciones masivas interfieren con eso. Por ejemplo, asumiendo que su mesa de foo
contiene una columna de id
y se asigna a una clase Foo
:
x = Foo(bar=1)
print x.id
# None
session.add(x)
session.flush()
# BEGIN
# INSERT INTO foo (bar) VALUES(1)
# COMMIT
print x.id
# 1
Desde SQLAlchemy recogió el valor de x.id
sin emitir otra consulta, se puede inferir que se obtuvo el valor directamente desde el INSERT
declaración. Si no es necesario el posterior acceso a los objetos creados a través de los mismos casos, puede omitir la capa ORM para su inserción:
Foo.__table__.insert().execute([{'bar': 1}, {'bar': 2}, {'bar': 3}])
# INSERT INTO foo (bar) VALUES ((1,), (2,), (3,))
SQLAlchemy no puede coincidir con estas nuevas filas con objetos existentes, por lo tendrá que consultarlos nuevamente para cualquier operación posterior.
En lo que respecta a los datos obsoletos, es útil recordar que la sesión no tiene una forma incorporada de saber cuándo se cambia la base de datos fuera de la sesión. Para acceder a datos modificados externamente a través de instancias existentes, las instancias deben estar marcadas como expiradas. Esto ocurre por defecto en session.commit()
, pero se puede hacer manualmente llamando al session.expire_all()
o session.expire(instance)
. Un ejemplo (SQL omitido):
x = Foo(bar=1)
session.add(x)
session.commit()
print x.bar
# 1
foo.update().execute(bar=42)
print x.bar
# 1
session.expire(x)
print x.bar
# 42
session.commit()
expira x
, por lo que la primera sentencia print implícitamente se abre una nueva transacción y re-consultas atributos x
's. Si comenta la primera declaración impresa, notará que la segunda ahora recoge el valor correcto, porque la nueva consulta no se emite hasta después de la actualización.
Esto tiene sentido desde el punto de vista del aislamiento transaccional: solo debe elegir modificaciones externas entre transacciones. Si esto le está causando problemas, le sugiero que aclare o vuelva a pensar en los límites de las transacciones de su aplicación en lugar de llegar inmediatamente al session.expire_all()
.
Esto podría ayudar: http://stackoverflow.com/questions/270879/efficiently-updating-database-using-sqlalchemy-orm/278606#278606 –
Nick, entiendo que esto es un * muy * antiguo puesto . ¿Sería posible actualizar el título a algo * correcto * como "inserción de múltiples registros con SQLAlchemy ORM". Las instrucciones de inserción de múltiples registros como la que ha proporcionado son bastante diferentes de las operaciones de carga masiva a nivel de base de datos. Las inserciones masivas están destinadas a la carga de datos a 1k +, generalmente de grandes conjuntos de datos y hechos por administradores de aplicaciones, no por operaciones REST o código de nivel de aplicación ... Usemos nuestra nomenclatura correctamente. – W4t3randWind