如何使用 alembic 从父级级联删除?
How to cascade delete from parent using alembic?
也许我在这里遗漏了一些非常简单的东西,但我有一个 postgresql 数据库,其中有几个结构如下的表:
- releases
|- releases_contributions
|- releases_primary contributions
|- recording
|- recording_contributions
|- recording_primary_contributions
其中 releases_contributions
、releases_primary_contributions
和 recording
都有一列具有与自动生成的 releases_id
关联的外键。
我已经修改以更新 ondelete
参数:
op.alter_column('recording', 'releases_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
op.alter_column('recording_contributions', 'recording_fk_id', sa.ForeignKey('recording.recording_id', ondelete='CASCADE'))
op.alter_column('recording_primary_contributions', 'recording_fk_id', sa.ForeignKey('recording.recording_id', ondelete='CASCADE'))
op.alter_column('releases_contributions', 'releases_fk_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
op.alter_column('releases_primary_contributions', 'releases_fk_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
当然,在我最初的 alembic 升级中,我有这个:
op.add_column('releases', 'releases_id', primary_key=True, autoincrement=True)
我正在尝试删除 releases
中的一行
delete from releases where releases_id=1;
然后向下级联到其他表并删除任何具有该版本的外键行。
但是每当我 运行 该命令时,我都会收到以下错误:
ERROR: update or delete on table "releases" violates foreign key constraint "releases_contributions_releases_fk_id_fkey" on table "releases_contributions"
DETAIL: Key (releases_id)=(1) is still referenced from table "releases_contributions".
我在这里错过了什么?
使用下面的 downgrades/upgrades 更新 alembic 修订版,然后 运行 alembic downgrade -1
和 alembic upgrade head
解决了这个问题。
def upgrade():
op.alter_column('recording', 'releases_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
op.alter_column('recording_contributions', 'recording_fk_id', sa.ForeignKey('recording.recording_id', ondelete='CASCADE'))
op.alter_column('recording_primary_contributions', 'recording_fk_id', sa.ForeignKey('recording.recording_id', ondelete='CASCADE'))
op.alter_column('releases_contributions', 'releases_fk_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
op.alter_column('releases_primary_contributions', 'releases_fk_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
def downgrade():
op.drop_contraint('releases_id', 'releases')
op.drop_contraint('releases_id', 'recording')
op.drop_contraint('releases_fk_id', 'releases_contributions')
op.drop_contraint('releases_fk_id', 'releases_primary_contributions')
op.drop_contraint('recording_fk_id', 'recording_contributions')
op.drop_contraint('recording_fk_id', 'recording_primary_contributions')
也许我在这里遗漏了一些非常简单的东西,但我有一个 postgresql 数据库,其中有几个结构如下的表:
- releases
|- releases_contributions
|- releases_primary contributions
|- recording
|- recording_contributions
|- recording_primary_contributions
其中 releases_contributions
、releases_primary_contributions
和 recording
都有一列具有与自动生成的 releases_id
关联的外键。
我已经修改以更新 ondelete
参数:
op.alter_column('recording', 'releases_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
op.alter_column('recording_contributions', 'recording_fk_id', sa.ForeignKey('recording.recording_id', ondelete='CASCADE'))
op.alter_column('recording_primary_contributions', 'recording_fk_id', sa.ForeignKey('recording.recording_id', ondelete='CASCADE'))
op.alter_column('releases_contributions', 'releases_fk_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
op.alter_column('releases_primary_contributions', 'releases_fk_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
当然,在我最初的 alembic 升级中,我有这个:
op.add_column('releases', 'releases_id', primary_key=True, autoincrement=True)
我正在尝试删除 releases
delete from releases where releases_id=1;
然后向下级联到其他表并删除任何具有该版本的外键行。
但是每当我 运行 该命令时,我都会收到以下错误:
ERROR: update or delete on table "releases" violates foreign key constraint "releases_contributions_releases_fk_id_fkey" on table "releases_contributions"
DETAIL: Key (releases_id)=(1) is still referenced from table "releases_contributions".
我在这里错过了什么?
使用下面的 downgrades/upgrades 更新 alembic 修订版,然后 运行 alembic downgrade -1
和 alembic upgrade head
解决了这个问题。
def upgrade():
op.alter_column('recording', 'releases_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
op.alter_column('recording_contributions', 'recording_fk_id', sa.ForeignKey('recording.recording_id', ondelete='CASCADE'))
op.alter_column('recording_primary_contributions', 'recording_fk_id', sa.ForeignKey('recording.recording_id', ondelete='CASCADE'))
op.alter_column('releases_contributions', 'releases_fk_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
op.alter_column('releases_primary_contributions', 'releases_fk_id', sa.ForeignKey('releases.releases_id', ondelete='CASCADE'))
def downgrade():
op.drop_contraint('releases_id', 'releases')
op.drop_contraint('releases_id', 'recording')
op.drop_contraint('releases_fk_id', 'releases_contributions')
op.drop_contraint('releases_fk_id', 'releases_primary_contributions')
op.drop_contraint('recording_fk_id', 'recording_contributions')
op.drop_contraint('recording_fk_id', 'recording_primary_contributions')