web-dev-qa-db-ja.com

SQLAlchemy、データベースの内容を消去しますが、スキーマは削除しません

既存のデータベースに基づいたPylonsアプリを開発しているので、リフレクションを使用しています。テストデータベースの作成に使用したスキーマを含むSQLファイルがあります。 drop_allcreate_allを単純に使用できない理由です。

いくつかの単体テストを書きたいのですが、各テストの後にデータベースの内容をクリアするという問題に直面しました。すべてのデータを消去したいが、テーブルはそのままにしておきたい。これは可能ですか?

アプリケーションはPostgresを使用し、これはテストにも使用する必要があります。

46
Juliusz Gonera

SQLAlchemy Googleグループで同じことを聞いたところ、うまく機能しているように見えるレシピがありました(すべてのテーブルが空になっています)。リファレンスについては、 スレッド を参照してください。

私のコード(抜粋)は次のようになります:

import contextlib
from sqlalchemy import MetaData

meta = MetaData()

with contextlib.closing(engine.connect()) as con:
    trans = con.begin()
    for table in reversed(meta.sorted_tables):
        con.execute(table.delete())
    trans.commit()

編集:コードを変更して、テーブルを逆の順序で削除しました。おそらくこれにより、親よりも先に子が削除されます。

48
aknuds1

TRUNCATEを使用するPostgreSQLの場合:

with contextlib.closing(engine.connect()) as con:
    trans = con.begin()
    con.execute('TRUNCATE {} RESTART IDENTITY;'.format(
        ','.join(table.name 
                 for table in reversed(Base.metadata.sorted_tables))))
    trans.commit()

注意: RESTART IDENTITY;は、すべてのシーケンスも確実にリセットされます。ただし、これは@ aknuds1によるDELETEレシピよりも50%遅くなります。

別のレシピは、最初にすべてのテーブルを削除してから、それらを再作成することです。これはさらに50%遅くなります。

Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
12
kolypto