防止Alembic自动生成表

时间:2018-10-05 09:05:47

标签: python flask sqlalchemy 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修订版--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不要自动创建任何表,而仅运行我创建的脚本?

1 个答案:

答案 0 :(得分:2)

您的迁移明确创建了一个Data表:

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

因此,如果您的Data表已经存在,因为您已经手动创建了它,则出现错误是正常的。

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


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

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

您可以(按我的偏好级别排序):

  1. 删除现有表,并让Alembic创建它们。这样,Alembic只需按照迁移中的声明创建表并更新其历史记录即可。

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

  3. 从根迁移的create_table函数中删除upgrade()指令(并且可能从drop_table函数中删除downgrade())。这样,Alembic将在不尝试创建现有表的情况下运行迁移,并且它应该可以工作。还将记录其历史记录中应用的迁移。

  4. 仅在表不存在时才在迁移中添加测试以创建表,但是在这种情况下,您将如何管理降级?