Alembic 添加不能为空的列

对于如何使用 alembic 对已有数据的表添加一个 nullable 为 false 的列的记录。

Published @ Aug 14, 2014

当我们对一个已存在数据的 Table 中添加一个 nullable=False 的列时,通常 alembic 会直接报错,因为它不知道要给这个列赋予什么值,所以会默认给个 NULL 的值,但是这个值与 nullable=False 的规则冲突了。

通常这种不能为空的列都是应该有一个默认值的,所以可以直接在 alembic 中指定这个列的默认值:

op.add_column('callroom', sa.Column('consulvalid', sa.Integer(), nullable=True, server_default=text("0")))

但也有可能这个默认值只想在 Python 的 orm 环境中定义,不想定义到数据库中,比如

class MyClass(Base):
    name = Column(Unicode(40), default=u'hello')

这种情况下,可以这么修改 alembic 迁移脚本:

from sqlalchemy.sql import table, column
op.add_column('callroom', sa.Column('consulvalid', sa.Boolean(), nullable=True))
callroom = table("callroom", column("consulvalid", sa.Boolean()))
op.execute(callroom.update().values(consulvalid=False))
op.alter_column("callroom", "consulvalid", nullable=False)

即先增加了一个 nullable=True 的列,然后将这个列设置默认值后,再改成 nullable=False

2015-2-10 更新

上面的方法适用于给一个列赋一个固定值,但是如果我们想要把另一个列的值赋予这个新增列怎么办呢。

凭感觉写了一下实现方法,试了一下果然成功了。目前没精力去研究清楚原理,就先记录下来吧。

from sqlalchemy.sql import table, column
topic = table("forum_topic", 
              column("update_time", sa.DateTime()), 
              column("pintop_time", sa.DateTime()))
op.execute(topic.update().values(pintop_time=topic.c.update_time))
END

章节导航: