Bezdepbonusu7Программирование: статьи и ответы

Вопрос

SQLAlchemy, очистить содержимое базы данных, но не отбрасывать схему

Автор вопроса: Juliusz GoneraОтветов: 3

Я разрабатываю приложение Pylons, основанное на существующей базе данных, поэтому я использую отражение. У меня есть файл SQL со схемой, которую я использовал для создания своей тестовой базы данных. Вот почему я не могу просто использовать drop_all и create_all.

Я хотел бы написать несколько модульных тестов и столкнулся с проблемой очистки содержимого базы данных после каждого теста. Я просто хочу стереть все данные, но оставить таблицы нетронутыми. Это возможно?

Приложение использует Postgres, и это то, что нужно также использовать для тестов.

  • Вам следует использовать транзакции. docs.sqlalchemy. org / en / rel_0_7 / orm / charlax 12.09.2012

pythonsqlalchemypylons

Ответы

Ответ 1 · рейтинг 60 · aknuds1

Я спросил о том же в группе Google SQLAlchemy и получил рецепт, который, похоже, работает хорошо (все мои таблицы опустошены). См. ветку для справки.

Мой код (отрывок) выглядит так:

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()

Изменить: я изменил код, чтобы удалить таблицы в обратном порядке; якобы это должно гарантировать, что дети будут удалены раньше родителей.

Ответ 2 · рейтинг 16 · kolypto

Для PostgreSQL с использованием TRUNCATE:

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; гарантирует, что все последовательности также будут сброшены. Однако это медленнее, чем DELETE рецепт @ aknuds1 на 50%.

Другой рецепт - сначала удалить все таблицы, а затем воссоздать их. Это медленнее еще на 50%:

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

Ответ 3 · рейтинг -4 · Joe L.

Как насчет использования усечения:

TRUNCATE [ТАБЛИЦА] имя [, ...]

(http://www.postgresql.org/docs/8.4/static/sql-truncate.html)

Это удалит все записи в таблице, но оставит схему в действии.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы