SQLAlchemy _ Alembic을 다운그레이드하려면 ForeignKey 필드에 이름을 입력해야 합니다.

한 줄 요약

*강등시키려면 *Alembic의 ForeignKey 필드에 이름을 입력해야 합니다.

*외래 키 필드는 다른 테이블의 기본 키를 참조하는 테이블 필드를 나타냅니다.

*Alembic은 Python용 데이터베이스 마이그레이션 도구입니다.

*다운그레이드는 이전 버전으로 돌아가는 것을 의미합니다.


문제 상황

상위 엔터티를 삭제하면 하위 엔터티도 삭제할 수 있습니다.

ondelete=”CASCADE” 옵션을 parent_id 하위 필드에 추가했습니다.

class Child(Base):
    __tablename__ = "child"

    id = sa.Column(UUID(as_uuid=True), primary_key=True)
    parent_id = sa.Column(
        UUID(as_uuid=True),
        ForeignKey("parent.id", ondelete="CASCADE"), # <-- 이 부분
        nullable=False,
        index=True,
    )

Alembic 버전 파일도 생성되어 마이그레이션이 정상적으로 진행되었습니다!

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint('child_parent_id_fkey', 'child', type_='foreignkey')
    op.create_foreign_key('child_parent_id_fkey', 'child', 'parent', ('parent_id'), ('id'), ondelete="CASCADE")
    # ### end Alembic commands ###

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint('child_parent_id_fkey', 'child', type_='foreignkey')
    op.create_foreign_key('child_parent_id_fkey', 'child', 'parent', ('parent_id'), ('id'))
    # ### end Alembic commands ###

그러나 버전을 다운그레이드하면 다음과 같은 오류 메시지가 나타납니다!?

sqlalchemy.exc.CompileError: Can't emit DROP CONSTRAINT for constraint ForeignKeyConstraint(<sqlalchemy.sql.base.DedupeColumnCollection object at 0xffff80c086d0>, None, table=Table('child', MetaData(), schema=None)); it has no name



해결

문제의 원인은 버전 파일에서 Alembic이 임의로 지정한 이름(child_parent_id_fkey)이 실제 ForeignKey 필드에 정의되어 있지 않기 때문입니다.

SQLAlchemy는 이름이 정의되지 않았기 때문에 외래 키 제약 조건에서 DROP CONSTRAINT 문을 실행할 수 없습니다! (깨달음 포인트)

이 문제를 해결하려면 ForeignKey 필드를 정의할 때 이름을 직접 지정해야 합니다. B. 아래와 같이 name=”child_parent_id_fkey”.

class Child(Base):
    __tablename__ = "child"

    id = sa.Column(UUID(as_uuid=True), primary_key=True)
    parent_id = sa.Column(
        UUID(as_uuid=True),
        ForeignKey("parent.id", name="child_parent_id_fkey", ondelete="CASCADE"),
        nullable=False,
        index=True,
    )

이를 반영하도록 버전 파일의 코드를 변경할 수 있지만 DB 볼륨을 완전히 삭제하고 다시 마이그레이션하십시오.



함께 보면 좋은 공문서

캐스케이드 — SQLAlchemy 1.4 문서