带自引用外键的Alembic SQLite ALTER表
SQLite数据库的Alembic迁移:带自引用外键的Alembic SQLite ALTER表,sqlite,foreign-key-relationship,database-migration,alembic,Sqlite,Foreign Key Relationship,Database Migration,Alembic,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'])
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\u id
引用同一个表my\u table
的id
,创建对名为\u alembic\u batch\u temp
的表的引用:
CREATE TABLE "my_table" (
id VARCHAR(24) NOT NULL,
parent_id VARCHAR(24),
PRIMARY KEY (id),
CONSTRAINT parent_constraint FOREIGN KEY(parent_id) REFERENCES _alembic_batch_temp (id)
)
如何在更改表时创建自引用约束?经过一些研究,我发现这里的问题是Alembic执行批迁移的方式。简而言之,在Alembic的当前版本(0.7.6)中,不可能通过迁移创建与self的关系
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 migration_temp_table;
DROP TABLE my_table;
ALTER TABLE _alembic_batch_temp RENAME TO my_table;
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;
INSERT INTO _alembic_batch_temp (id) SELECT id FROM my_table;
DROP TABLE migration_temp_table;
显然,至少在SQLite 3.13.0(.Net 1.0.102.0)中不再需要您的变通方法。我用这个版本测试了这个完全相同的场景(第一个场景),它按照预期工作:使用表重命名自引用。我甚至尝试了一个ON-DELETE级联,我的数据保持在原来的位置:)