如何使用sqlalchemy-migrate将列类型从字符变为整数

时间:2013-03-05 16:48:02

标签: python postgresql sqlalchemy sqlalchemy-migrate

我正在使用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?或者有其他方法可以避免我在上面发布的错误吗?

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

看起来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')

BTW从String迁移到Integer可能由于不同的原因而失败 - 当列值包含一些无法转换为数字的值时。因此,我会在应用程序逻辑中添加一些额外的验证,以便以后保持降级迁移。