Até onde eu sei, não há como fazer com que o ORM emita inserções em massa. Acredito que a razão subjacente é que o SQLAlchemy precisa acompanhar a identidade de cada objeto (ou seja, novas chaves primárias), e inserções em massa interferem nisso. Por exemplo, supondo que sua foo
tabela contenha uma id
coluna e seja mapeada para uma 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
Como o SQLAlchemy selecionou o valor x.id
sem emitir outra consulta, podemos inferir que ele obteve o valor diretamente da INSERT
instrução Se você não precisar de acesso subseqüente aos objetos criados pelas mesmas instâncias, poderá pular a camada ORM da sua inserção:
Foo.__table__.insert().execute([{'bar': 1}, {'bar': 2}, {'bar': 3}])
# INSERT INTO foo (bar) VALUES ((1,), (2,), (3,))
O SQLAlchemy não pode corresponder essas novas linhas a nenhum objeto existente; portanto, você precisará consultá-las novamente para operações subsequentes.
No que diz respeito aos dados obsoletos, é útil lembrar que a sessão não possui uma maneira integrada de saber quando o banco de dados é alterado fora da sessão. Para acessar dados modificados externamente através de instâncias existentes, as instâncias devem ser marcadas como expiradas . Isso acontece por padrão session.commit()
, mas pode ser feito manualmente chamando session.expire_all()
ou session.expire(instance)
. Um exemplo (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
, então a primeira instrução de impressão abre implicitamente uma nova transação e consulta novamente os x
atributos. Se você comentar a primeira declaração de impressão, notará que a segunda agora seleciona o valor correto, porque a nova consulta não é emitida até depois da atualização.
Isso faz sentido do ponto de vista do isolamento transacional - você só deve captar modificações externas entre transações. Se isso estiver causando problemas, sugiro que você esclareça ou repense os limites de transação do aplicativo em vez de procurar imediatamente session.expire_all()
.