SQLite数据库的Alembic迁移:
def upgrade():
with op.batch_alter_table('my_table') as batch_op:
batch_op.add_column(sa.Column('parent_id', sa.String(24)))
batch_op.create_foreign_key('parent_constraint', 'my_table', ['parent_id'], ['id'])
应该创建引用同一个表parent_id
的{{1}}的外键id
,创建对名为my_table
的表的引用:
_alembic_batch_temp
如何在更改表时创建自引用约束?
答案 0 :(得分:5)
经过一番研究后,我发现这里的问题是Alembic进行批量迁移的方式。简而言之,在Alembic的当前版本(0.7.6)中,不可能通过迁移创建与self的关系。
如Alembic documentation所述,要进行迁移,将使用临时名称创建新表,并从alter table更改 码。在这种情况下:
CREATE TABLE _alembic_batch_temp (
id VARCHAR(24) NOT NULL,
parent_id VARCHAR(24),
PRIMARY KEY (id),
CONSTRAINT parent_constraint FOREIGN KEY(parent_id) REFERENCES _alembic_batch_temp (id)
)
表中填充了旧表中的数据:
INSERT INTO _alembic_batch_temp (id) SELECT id FROM my_table;
然后删除旧表:
DROP TABLE my_table;
最后,新创建的表被重命名为它的正确名称:
ALTER TABLE _alembic_batch_temp RENAME TO my_table;
这种做事方式的问题已在第一个代码段中显示出来。新创建的外键引用临时表,一旦创建它,由于SQLite中的限制,它无法更改。因此,在重新命名表后,您最终会得到您提供的表格:
CREATE TABLE "my_table" ( # new name
id VARCHAR(24) NOT NULL,
parent_id VARCHAR(24),
PRIMARY KEY (id),
CONSTRAINT parent_constraint FOREIGN KEY(parent_id) REFERENCES _alembic_batch_temp (id) # old reference
)
要避免这种情况,您可以手动创建批量迁移:
将旧表重命名为某个临时名称:
ALTER TABLE my_table RENAME TO migration_temp_table;
使用正确的名称和正确的参考创建新表:
CREATE TABLE my_table (
id VARCHAR(24) NOT NULL,
parent_id VARCHAR(24),
PRIMARY KEY (id),
CONSTRAINT parent_constraint FOREIGN KEY(parent_id) REFERENCES my_table (id)
)
复制数据:
INSERT INTO my_table (id) SELECT id FROM migration_temp_table;
删除旧表:
DROP TABLE migration_temp_table;