【问题标题】:How to migrate data in sqlite alembic migration?如何在 sqlite alembic 迁移中迁移数据?
【发布时间】:2016-09-06 13:07:09
【问题描述】:

我有一列 goods.visible(布尔值),我想用 goods.status(枚举)替换它。

我需要用另一列替换一列并使用 sqlalchemy 迁移数据(以使用其数据类型转换机制)。由于 sqlite 对此不支持 ALTER TABLE,因此我必须为此使用 batch_alter_table alembic 操作。

我的迁移如下所示。它抛出sqlite3.OperationalError: no such column: goods.status,因为在我的旧表中没有这样的列(新表是为使用批处理迁移而创建的)

def upgrade():
    with op.batch_alter_table('goods') as batch_op:
        batch_op.add_column(sa.Column('status', sa.Enum('published', 'unpublished', 'deleted'), nullable=True))

        conn = op.get_bind()
        Session = sa.orm.sessionmaker()
        session = Session(bind=conn)
        for good in session.query(Good):
            # I want to perform some data updates & insert data into new column
        batch_op.drop_column('visible')

如果我要添加 load_only 以指定要从表中选择的列: sqlite3.OperationalError: no such column: goods.status

我会收到错误sqlalchemy.exc.ArgumentError: Can't find property named 'visible' on the mapped entity Mapper|Good|goods in this Query.。我明白我为什么得到它 - 我的模型中没有更多可见的属性。

在这种情况下如何使用 alembic 迁移数据?

我尝试使用原始查询.. 但它说没有表:

    s = sa.sql.select([sa.sql.text('goods.*')])
    for row in conn.execute(s):
        print(row)

Hovewer 检查器显示 goods 表:

 inspector = sa.inspect(conn.engine)
    for table_name in inspector.get_table_names():
        print(table_name)
        for column in inspector.get_columns(table_name):
            print("Column: %s" % column['name'])

展示

goods
Column: id
Column: name
Column: price
Column: visible

【问题讨论】:

  • 尚不能解决您帖子的其余部分,但sqlite3.OperationalError: no such column: goods.status 的原因似乎是实际上with 块内的批处理操作collects instructions registered through batch_op 然后在__exit__ 执行他们。所以在 with 块中确实没有 status 列。

标签: python sqlalchemy


【解决方案1】:

您可以有多个 batch_alter_table 块。使用第一个添加新列,然后(在该块之外和之后)运行您的业务逻辑(在这种情况下将您的布尔值转换为一些枚举值),然后使用另一个块删除该列。

类似:-

def upgrade():
    with op.batch_alter_table('goods') as batch_op:
        batch_op.add_column(sa.Column('status', sa.Enum('published', 'unpublished', 'deleted'), nullable=True))
    # Do your business logic here
    with op.batch_alter_table('goods') as batch_op:
        batch_op.drop_column('visible')

【讨论】:

    猜你喜欢
    • 2013-10-20
    • 2013-07-31
    • 2020-02-17
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 2016-05-21
    • 2014-05-18
    相关资源
    最近更新 更多