2013-01-17 17 views
9

Ho bisogno di inserire/aggiornare le righe di massa tramite SQLAlchemy. E ottieni righe inserite.SQLAlchemy: impedire la chiusura automatica

ho cercato di farlo 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) 

E con motore:

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 stessa risposta è un oggetto è stato chiuso automaticamente. Come prevenirlo?

risposta

8

Prima risposta - su "prevenzione chiusura automatica".

SQLAlchemy esegue DBAPI execute() o executemany() con insert e non esegue alcuna query di selezione. Quindi l'eccezione che hai è il comportamento previsto. Oggetto ResultProxy restituito dopo l'esecuzione della query di inserimento avvolge il cursore DB-API che non consente di eseguire .fetchall() su di esso. Una volta che .fetchall() non riesce, ResultProxy restituisce all'utente l'eccezione della sega.

L'unica informazione che è possibile ottenere dopo l'operazione di inserimento/aggiornamento/cancellazione sarà il numero di righe interessate o il valore della chiave primaria dopo l'incremento automatico (a seconda del database e del driver del database).

Se il vostro obiettivo è quello di ricevere questo tipo di informazioni, consigliamo di verificare ResultProxy methods and attributes come:

  • .inserted_primary_key
  • .last_inserted_params()
  • .lastrowid
  • ecc

Seconda risposta - su "come fare bulk insert/update e ottenere resulti ng righe ".

Non è possibile caricare le righe inserite mentre si esegue una query di inserimento singolo utilizzando DBAPI. SQL Exchemy SQL Expression API che stai utilizzando per fare inserimenti/aggiornamenti di massa non fornisce tale funzionalità. SQLAlchemy esegue la chiamata execemany() DBAPI e si basa sull'implementazione del driver. Vedi this section of documentation per i dettagli.

La soluzione sarebbe progettare la tabella in modo che ogni record avrebbe la chiave naturale per identificare i record (combinazione di valori delle colonne che identificano i record in modo univoco). Quindi inserire/aggiornare/selezionare le query sarebbe in grado di indirizzare un record. Dopo averlo fatto, è possibile eseguire prima l'inserimento/aggiornamento di massa e quindi eseguire la query di selezione con la chiave nativa. Pertanto non è necessario conoscere il valore della chiave primaria autoincrementata.

Un'altra opzione: è possibile utilizzare SQLAlchemy Object Relational API per la creazione di oggetti, quindi SQLAlchemy potrebbe tentare di ottimizzare l'inserimento in una query con executemany. Ha funzionato per me durante l'utilizzo di Oracle DB. Non ci sarà alcuna ottimizzazione per gli aggiornamenti fuori dalla scatola. Controlla this SO question per idee di aggiornamento di massa efficienti

+2

Grazie, mi hai ispirato. – I159

Problemi correlati