Hasta donde yo sé, no hay forma de que el ORM emita inserciones masivas. 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, suponiendo que su foo
tabla contiene una id
columna y está asignada a una Foo
clase:
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
Como SQLAlchemy recogió el valor x.id
sin emitir otra consulta, podemos inferir que obtuvo el valor directamente de la INSERT
declaración. Si no necesita acceso posterior a los objetos creados a través de las mismas instancias, 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 hacer coincidir estas nuevas filas con ningún objeto existente, por lo que tendrá que consultarlas 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 integrada 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 marcarse como caducadas . Esto ocurre de forma predeterminada en session.commit()
, pero se puede hacer manualmente llamando 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 declaración de impresión abre implícitamente una nueva transacción y vuelve a consultar x
los atributos. 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 recoger modificaciones externas entre transacciones. Si esto le está causando problemas, sugeriría aclarar o repensar los límites de transacción de su aplicación en lugar de buscarlos de inmediato session.expire_all()
.