我一直在使用SQLAlchemy和Alembic迁移的设置以及后端的Postgres DB。我一直在使用某些DB-Models中的枚举作为数据类型,我一直在使用SQLAlchemy中的Enum-Type,并且(因为这个)也在Postgres中使用。在整个持续开发过程中,我决定用整数替换这些枚举,原因有些较小(包括在添加新值时具有更高的灵活性,这需要现在改变数据类型的DB迁移并改变alembic中的那些是相当复杂的对于其他数据库系统来说,enums似乎不像int那样可移植)。我必须创建一个迁移,因为这会使用alembic迁移将枚举列的数据类型更改为int。
遗憾的是,我还没有找到任何转换方法,这将允许我在整个迁移过程中保留旧值。我一直在使用IntEnums,它将枚举值映射到python中的整数,但Postgres不在内部使用此映射,因此在将其转换为整数时,它没有关于枚举的假设值的信息。从我的角度来看,在应用alter table查询时,我必须以某种方式提供枚举名到整数的显式映射。 Postgres提供了using语句,但是我一直无法找到如何使用它来将我的枚举值中的值映射到python一直使用的新/旧整数值。
那么如果我必须手动为其提供映射,那么如果它应该将旧的(基于枚举的)值映射到新的(基于int的)值,那么这样的using语句将如何?
这种枚举的一个例子:
class SexEnum(enum.IntEnum):
male = 0
female = 1
列(DB中的旧):
sex = db.Column(db.Enum(SexEnum))
专栏(新):
sex = db.Column(db.Integer)
现在迁移命令:
op.alter_column('users', 'sex',
type_=sa.Integer, postgresql_using='null')
Null可能必须用其他东西替换。
此外,应该注意的是,如果迁移尽可能与其他数据库系统兼容,那将会很好,这会迫使我使用另一个系统,而不是使用using语句,不是吗?
好的找到了。感谢Ilja的CASE提示。
基本上用'null'代替'null'
'(CASE sex WHEN \'male\'... END)'
这使得迁移无需以其他方式设置所有这些值。我不认为这完全符合我的可移植性要求,只是因为我仍在使用postgres的using子句。除此之外,简单的案例陈述也有效。