9

SQLAlchemy を介して一括行を挿入/更新する必要があります。挿入された行を取得します。

私はsession.executeでそれをやろうとしました:

 >>> posts = db.session.execute(Post.__table__.insert(), [{'title': 'dfghdfg', 'content': 'sdfgsdf', 'topic': topic}]*2)
 >>> posts.fetchall()

 ResourceClosedError                       Traceback (most recent call last)

そしてエンジン付き:

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.

同じ応答は、オブジェクトが自動的に閉じられたことです。それを防ぐ方法は?

4

1 に答える 1

9

最初の答え-「自動クローズの防止」について。

SQLAlchemyは、挿入を使用してDBAPI execute()またはexecutemany()を実行し、selectクエリを実行しません。したがって、あなたが持っている例外は期待される振る舞いです。挿入クエリの実行後に返されるResultProxyオブジェクトは、それを実行できないDB-APIカーソルをラップします.fetchall()。失敗すると、 ResultProxy .fetchall()はユーザーに見た例外を返します。

挿入/更新/削除操作の後に取得できる唯一の情報は、影響を受ける行の数または自動インクリメント後の主キーの値です(データベースとデータベースドライバーによって異なります)。

この種の情報を受け取ることが目標である場合は、次のようなResultProxyメソッドと属性を確認することを検討してください。

  • .inserted_primary_key
  • .last_inserted_pa​​rams()
  • .lastrowid

2番目の答え-「一括挿入/更新を実行して結果の行を取得する方法」について。

DBAPIを使用して単一の挿入クエリを実行しているときに、挿入された行をロードする方法はありません。一括挿入/更新を行うために使用しているSQLAlchemySQLExpression APIも、そのような機能を提供していません。SQLAlchemyはDBAPIexecutemany()呼び出しを実行し、ドライバーの実装に依存します。詳細については、ドキュメントのこのセクションを参照してください。

解決策は、すべてのレコードがレコードを識別するための自然キー(レコードを一意の方法で識別する列の値の組み合わせ)を持つようにテーブルを設計することです。したがって、挿入/更新/選択クエリは1つのレコードをターゲットにすることができます。実行後、最初に一括挿入/更新を実行してから、自然キーによる選択クエリを実行することができます。したがって、自動インクリメントされた主キー値を知る必要はありません。

別のオプション:オブジェクトを作成するためにSQLAlchemy Object Relational APIを使用できる場合があります-次に、SQLAlchemyは、executemanyを使用して1つのクエリを実行するように挿入を最適化しようとする場合があります。OracleDBを使用しているときに機能しました。すぐに使用できる更新の最適化はありません。効率的な一括更新のアイデアについては、このSOの質問を確認してください

于 2013-01-17T21:20:20.327 に答える