防止 alembic 自动生成表

Prevent alembic from autogenerating tables

我是 alembic 的新手,所以我可能会漏掉它的概念中的一点,但问题是。

我在烧瓶应用程序中有一些 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)

至此,我在我的数据库中手动创建了表并且一切正常。 为了以后让我的项目富有成效,我希望能够使用 alembic 迁移我的数据库。因为我将使用的一些表(在不同的模式中)是只读的并且由另一个程序创建,所以我只想迁移一些 sqlalchemy 表。因此我的升级脚本看起来像(由 alembic revision --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 不要自动创建任何表,而只 运行 我创建的脚本?

您的迁移明确创建 Data table:

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

所以如果你的Data table已经存在,因为你已经手动创建了它,那么出现错误是正常的。

编辑: 我不确定它何时执行,但您可能想尝试在数据库初始化脚本中注释 Base.metadata.create_all(engine) 行。我怀疑它会创建 tables。 我从未见过 alembic 在 运行 迁移之前创建 tables(这是迁移创建 tables 的工作),如果它不能解决您的问题,我认为问题是不是来自蒸馏器。


Alembic 旨在从一开始就管理您的数据库迁移,它并不假定您已经创建了 tables。

基本上它会创建一个 table 来保存应用于数据库的迁移历史记录。当您 运行 第一次升级时,还没有应用迁移,因此 Alembic 将尝试 运行 从根目录(其 down_revisionNone)开始的所有迁移升级到头一个。 在每次应用迁移时,它还会更新其历史记录 table 以反映数据库状态。

你可以(按我的喜好程度排序):

  1. 删除您已经存在的 table 并让 alembic 创建它们。这样,Alembic 只需创建在迁移中声明的 table 并更新其历史记录。

  2. 让 Alembic 相信它已经通过手动填充其历史记录应用了第一次迁移 table(我从未这样做过,但我认为这是可能的)。这样它就不会尝试再次应用它

  3. 从根迁移的 upgrade() 函数中删除 create_table 指令(可能还有 downgrade() 函数中的 drop_table )。这样,Alembic 将 运行 迁移而不尝试创建已经存在的 table,它应该可以工作。它还会记录在其自己的历史记录中应用的迁移。

  4. 在您的迁移中添加一个测试以创建 table 仅当它尚不存在时,但在这种情况下您将如何管理降级?