10

我正在尝试使用 alembic 将“id”主键列添加到已经存在的 MySQL 表中。我尝试了以下...

op.add_column('mytable', sa.Column('id', sa.Integer(), nullable=False))
op.alter_column('mytable', 'id', autoincrement=True, existing_type=sa.Integer(), existing_server_default=False, existing_nullable=False) 

但出现以下错误

sqlalchemy.exc.OperationalError: (OperationalError) (1075, 'Incorrect table definition; there can be only one auto column and it must be defined as a key') 'ALTER TABLE mytable CHANGE id id INTEGER NOT NULL AUTO_INCREMENT' ()

看起来alembic生成的sql语句没有PRIMARY KEY在alter语句的末尾添加。我可能错过了一些设置吗?

提前致谢!

4

2 回答 2

25

我花了一些时间研究 alembic 源代码,这似乎不受支持。您可以在创建表时指定主键,但不能在添加列时指定。事实上,它专门检查并且不会让你(链接到源):

# from alembic.operations.toimpl.add_column, line 132
for constraint in t.constraints:
    if not isinstance(constraint, sa_schema.PrimaryKeyConstraint):
        operations.impl.add_constraint(constraint)

我环顾四周,将主键添加到现有表可能会导致未指定的行为 - 主键不应该为空,因此您的引擎可能会也可能不会为现有行创建主键。有关更多信息,请参阅此 SO 讨论: 将自动增量主键插入现有表

我只是直接运行 alter 查询,如果需要,创建主键。

op.execute("ALTER TABLE mytable ADD id INT PRIMARY KEY AUTO_INCREMENT;")

如果您确实需要跨引擎兼容性,那么大锤将是(1)创建一个与旧表相同且具有主键的新表,(2)迁移所有数据,(3)删除旧表和(4 ) 重命名新表。

希望有帮助。

于 2012-12-07T06:02:51.037 回答
0

您必须删除表中的主键,然后创建一个包含您希望作为主键的所有列的新主键。

例如。在 psql 中使用\d <table name>定义模式,然后检查主键约束。

Indexes:
"enrollments_pkey" PRIMARY KEY, btree (se_crs_id, se_std_id)

然后在 alembic 中使用此信息

def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('enrollments', sa.Column(
    'se_semester', sa.String(length=30), nullable=False))
op.drop_constraint('enrollments_pkey', 'enrollments', type_='primary')
op.create_primary_key('enrollments_pkey', 'enrollments', [
                      'se_std_id', 'se_crs_id', 'se_semester'])

运行后的结果\d enrollments应该更新为

Indexes:
"enrollments_pkey" PRIMARY KEY, btree (se_std_id, se_crs_id, se_semester)

这个解决方案对我来说很好。

于 2021-08-10T12:51:35.570 回答