我正在使用sqlalchemy migrate更改Postgre SQL数据库中表中某列的类型。我使用的升级脚本是:
# -*- cofing: utf-8 -*-
from sqlalchemy import MetaData, Table, Column, String, Integer
from migrate import changeset
metadata = MetaData()
def upgrade(migrate_engine):
# ALTER TABLE courses ALTER COLUMN number SET DATA TYPE character varying;
metadata.bind = migrate_engine
courses = Table('courses', metadata, Column("number", Integer), extend_existing=True)
courses.c.number.alter(type=String)
def downgrade(migrate_engine):
# ALTER TABLE courses ALTER COLUMN number SET DATA TYPE integer;
metadata.bind = migrate_engine
courses = Table('courses', metadata, Column("number", String), extend_existing=True)
courses.c.number.alter(type=Integer, cast='numeric')
升级部分似乎可以工作,但降级总是失败,并出现以下错误:
sqlalchemy.exc.ProgrammingError: (ProgrammingError) column "number" cannot be cast to type integer
'\nALTER TABLE courses ALTER COLUMN number TYPE INTEGER' {}
现在,如果我使用的是纯SQL,我可以使用
ALTER TABLE courses ALTER COLUMN number TYPE INTEGER USING number::numeric
将列类型从character varying
改回integer
,但我不知道如何使用sqlalchemy migrate实现这一点。有没有办法强制sqlalchemy在
USING number::numeric
子句中包含ALTER
?或者有其他方法可以避免我在上面发布的错误吗?谢谢你的帮助。
最佳答案
看起来sqlalchemy.migrate不支持在postgresql从String列类型更改为Integer列类型时呈现有效查询。
在您的例子中,我将把它实现为直接查询执行并继续。
def downgrade(migrate_engine):
# ALTER TABLE courses ALTER COLUMN number SET DATA TYPE integer;
migrate_engine.execute('ALTER TABLE courses ALTER COLUMN number TYPE INTEGER USING number::numeric')
顺便说一句,从字符串迁移到整数可能会因为不同的原因而失败——因为列值将包含一些无法转换为数字的值。因此,我将在应用程序逻辑中添加一些额外的验证,以使以后的降级迁移成为可能。