我正在尝试使用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语句没有在alter语句末尾添加PRIMARY KEY
。我可以错过一些设置吗?
提前致谢!
答案 0 :(得分:20)
我花了一些时间来挖掘alembic源代码,但这似乎并不支持。您可以在创建表时指定主键,但在添加列时则不能。事实上,它专门检查并且不会让你(link to source):
# 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)
我环顾四周,向现有表添加主键可能会导致未指定的行为 - 主键不应为null,因此您的引擎可能会也可能不会为现有行创建主键。有关详细信息,请参阅此SO讨论:Insert auto increment primary key to existing table
我只是直接运行alter query,并在需要时创建主键。
op.execute("ALTER TABLE mytable ADD id INT PRIMARY KEY AUTO_INCREMENT;")
如果你真的需要跨引擎兼容性,那么大锤子就是(1)用主键创建一个与旧表相同的新表,(2)迁移所有数据,(3)删除旧表(4)重命名新表。
希望有所帮助。
答案 1 :(得分: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)
这个解决方案对我来说很好。