Предотвратить автоматическое создание таблиц в перегонном кубе

Я новичок в таком перегонном кубе, поэтому я могу упустить момент в его концепции, но вот вопрос.

у меня есть несколько таблиц sqlalchemy в приложении фляги, например:

class Data(Base):
__tablename__ = 'Data'
__table_args__ = {'schema': 'schema'}
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)

я инициализирую свои таблицы:

Base = declarative_base()
engine = create_engine(db_link, pool_size=100, max_overflow=0)
Base.metadata.create_all(engine)
Session = sessionmaker()
Session.configure(bind=engine)

К этому моменту я создал таблицы в своей базе данных вручную, и все работало хорошо. Чтобы позже начать продуктивно работать с моим проектом, я хочу иметь возможность перенести свою базу данных с помощью перегонного куба. Поскольку некоторые таблицы, которые я буду использовать (в другой схеме), доступны только для чтения и созданы другой программой, я хочу перенести только некоторые таблицы sqlalchemy. Поэтому мой сценарий обновления выглядит так (созданный перегонной версией --autogenerate):

revision = 'bb1d39b7eee1'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('Data',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(), nullable=False),
    sa.PrimaryKeyConstraint('id'),
    schema='schema'
    )
    ...

когда я теперь использую пустую базу данных для переноса моей схемы с помощью:

alembic upgrade head

я получаю следующую ошибку:

sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('42S01', "[42S01] [M
icrosoft][SQL Server Native Client 11.0][SQL Server]There is already an object n
amed 'Data' in the database. (2714) (SQLExecDirectW)") [SQL: '\nCREATE TABLE schema.
[Data] (\n\tid INTEGER NOT NULL IDENTITY(1,1), \n\tname VARCHAR(max) NOT NULL, \
 \n\tPRIMARY KEY (id), \n\tCHECK (IN (0, 1))\n)\n\n']

Похоже, что alembic автоматически создает все таблицы, а затем снова пытается создать эти таблицы в моем сценарии ревизии. Если это правда, как я могу сказать, что alembic не создает никаких таблиц автоматически, а запускает только те сценарии, которые я создаю?


person Florian H    schedule 05.10.2018    source источник
comment
Сколько таблиц вы уже создали в БД? Если число меньше, вы можете просто прочитать автоматически сгенерированный сценарий миграции перегонного куба и удалить записи create_table для тех, которые уже созданы. А затем запустить обновление   -  person suryasankar    schedule 08.10.2018
comment
где найти этот скрипт? Вы про скрипт ревизии (в папке с версиями)? Моя проблема в том, что alembic создает все таблицы, которые у меня есть в sqlalchemy, прежде чем запускать эти сценарии.   -  person Florian H    schedule 08.10.2018
comment
Я понимаю, что пытаюсь создать уже существующую ошибку таблицы из вопроса, даже если я пытаюсь запустить голову обновления во вновь созданной полностью пустой базе данных.   -  person Florian H    schedule 08.10.2018


Ответы (1)


Ваша миграция явно создает таблицу Data:

def upgrade():
    ...
    op.create_table('Data',
    ...

Поэтому, если ваша таблица Data уже существует, потому что вы уже создали ее вручную, это нормально, чтобы получить ошибку.

EDIT: я не уверен, что понимаю, когда он выполняется, но вы можете попробовать прокомментировать строку Base.metadata.create_all(engine) в сценарии инициализации вашей базы данных. Я подозреваю, что это для создания таблиц. Я никогда не видел, чтобы alembic создавал таблицы перед запуском миграции (это задача миграции для создания таблиц), если это не решит вашу проблему, я думаю, что проблема не в alembic.


Alembic предназначен для управления миграцией вашей базы данных с самого начала, он не предполагает, что вы уже создали свои таблицы.

По сути, он создает таблицу для хранения истории миграций, примененных к базе данных. Когда вы запускаете первое обновление, еще нет примененной миграции, поэтому Alembic попытается запустить все обновления миграции с корневого (чей down_revision равен None) до головного. При каждой примененной миграции он также обновляет свою таблицу истории, чтобы отразить состояние базы данных.

Вы можете (в порядке моего предпочтения):

  1. отбросьте уже существующие таблицы и позвольте alembic создать их. Таким образом, Alembic просто создает таблицу, как указано в миграции, и обновляет ее историю.

  2. заставить Alembic поверить, что он уже применил первую миграцию, вручную заполнив свою таблицу истории (я никогда этого не делал, но думаю, что это возможно). Таким образом, он не будет пытаться применить его снова

  3. удалите директивы create_table из функции upgrade() вашей корневой миграции (и, возможно, drop_table из функции downgrade()). Таким образом, Alembic запустит миграцию, не пытаясь создать уже существующие таблицы, и все должно работать. Он также запишет миграцию как примененную в своей собственной истории.

  4. добавьте тест в свою миграцию, чтобы создать таблицу, только если она еще не существует, но в этом случае как вы будете управлять понижением версии?

person Tryph    schedule 08.10.2018
comment
Моя проблема в том, что я хочу контролировать то, что делает перегонный куб. И поэтому я хочу, чтобы моя первая версия создавала таблицы, которые я хочу иметь (op.create_table). Я получаю эту ошибку, даже если я запускаю свой сценарий обновления перегонного куба в новой и пустой базе данных. Это подводит меня к выводу, что у меня активирована некоторая опция перегонного куба, которая создает все имеющиеся у меня таблицы sqlalchemy, независимо от моих сценариев ревизии, до того, как эти сценарии ревизии будут запущены. - person Florian H; 08.10.2018
comment
Спасибо, Base.metadata.create_all(engine) была проблемой. Создал ли он мои таблицы без перегонного куба и до этого, когда я запустил скрипт? Stackoverflow говорит мне, что мне нужно подождать 15 часов, прежде чем я смогу присудить награду, поэтому, если я забуду это завтра, не стесняйтесь помнить меня ;-) - person Florian H; 08.10.2018
comment
@Tryph Спасибо за ваше предложение в разделе «Правка» (комментарии строки Base.metadata.create_all (engine)). - person Tyrion; 12.05.2021