Autant que je sache, il n'y a aucun moyen pour que l'ORM émette des insertions en masse. Je crois que la raison sous-jacente est que SQLAlchemy doit garder une trace de l'identité de chaque objet (c'est-à-dire, les nouvelles clés primaires), et les insertions en masse interfèrent avec cela. Par exemple, en supposant que votre foo
table contient une id
colonne et est mappée à une Foo
classe:
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
Puisque SQLAlchemy a récupéré la valeur pour x.id
sans émettre une autre requête, nous pouvons en déduire qu'il a obtenu la valeur directement à partir de l' INSERT
instruction. Si vous n'avez pas besoin d'un accès ultérieur aux objets créés via les mêmes instances, vous pouvez ignorer la couche ORM pour votre insertion:
Foo.__table__.insert().execute([{'bar': 1}, {'bar': 2}, {'bar': 3}])
# INSERT INTO foo (bar) VALUES ((1,), (2,), (3,))
SQLAlchemy ne peut pas faire correspondre ces nouvelles lignes avec des objets existants, vous devrez donc les interroger à nouveau pour les opérations suivantes.
En ce qui concerne les données obsolètes, il est utile de se rappeler que la session n'a aucun moyen intégré de savoir quand la base de données est modifiée en dehors de la session. Pour accéder aux données modifiées en externe via des instances existantes, les instances doivent être marquées comme expirées . Cela se produit par défaut sur session.commit()
, mais peut être fait manuellement en appelantsession.expire_all()
ou session.expire(instance)
. Un exemple (SQL omis):
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()
expire x
, donc la première instruction print ouvre implicitement une nouvelle transaction et ré-interrogex
les attributs de. Si vous mettez en commentaire la première instruction d'impression, vous remarquerez que la seconde prend maintenant la valeur correcte, car la nouvelle requête n'est émise qu'après la mise à jour.
Cela a du sens du point de vue de l'isolation transactionnelle - vous ne devez prendre en compte que les modifications externes entre les transactions. Si cela vous cause des problèmes, je vous suggère de clarifier ou de repenser les limites de transaction de votre application au lieu de chercher immédiatement session.expire_all()
.