코드로 우주평화

SQLAlchemy _ ForeignKey 로 연결된 개체 한 번에 삭제하기 본문

나는 이렇게 학습한다/DB

SQLAlchemy _ ForeignKey 로 연결된 개체 한 번에 삭제하기

daco2020 2023. 3. 24. 18:13

 

 

SQLAlchemy에서는 cascading 옵션을 활용하여 관계된 개체(Entity)를 한 번에 삭제할 수 있다.

 

 

 

 

방법 1. 부모 relationship 에서 cascade 매개변수 지정

 

두 테이블 간의 관계를 정의할 때, 상위 개체와 하위 개체가 함께 삭제되도록 cascade 매개변수를 지정할 수 있다.

 

from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.orm import relationship


class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship('Child', cascade='delete')

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))

 

Parent 클래스가 Child 개체와 관계가 있음을 명시하고 cascade 매개변수를 "delete"로 설정했다. 이렇게 하면 부모 개체가 삭제될 때 관련된 모든 자식 개체도 삭제된다.

 

Parent 개체와 관련된 모든 Child 개체를 삭제하려면 간단히 session.delete(parent)를 호출하면 된다. ORM은 연결된 모든 Child 개체도 함께 삭제한다.

 

 

 


 

 

 

방법 2. 자식 ForeignKey 에 ondelete 제약 조건 추가

 

자식 테이블에서 ForeignKey 제약 조건을 정의할 때, ondelete="CASCADE" 옵션을 추가할 수 있다. 

 

from sqlalchemy import Column, Integer, ForeignKey


class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey("parent.id", ondelete="CASCADE"))

 



Child 클래스의 parent_id 필드에 ondelete 매개변수를 추가하고 "CASCADE"로 지정했다. 이 방법은 부모 테이블에 자식과의 관계가 정의되어 있지 않아도 된다.

 

부모 테이블에 정의되어 있지 않아도 Parent 개체가 삭제될 때 Child 개체들도 함께 삭제 된다.

 

 

 


 

 

둘의 차이점

 

방법1, 방법2 모두 부모 개체가 삭제될 때 관련된 개체도 함께 삭제하지만 둘의 동작 방식에는 차이가 있다. 

 

방법1(relationship - cascade)은 ORM 계층에서 관계를 정의할 때 사용하지만, 방법2(ForeignKey - ondelete)는 데이터베이스 스키마 수준에서 외래 키 제약 조건을 정의할 때 사용한다. 

 

공식문서에서는 방법2가 더 효율적이라고 말한다. ORM 과 달리, 데이터베이스는 여러 관계의 CASCADE 연산을 한 번에 수행할 수 있기 때문이다. 

 

이 둘의 사용법과 차이에 대해 더 자세히 알고 싶다면 아래 공식문서를 참고하자.

 

 

 


 

 

참고 문서

 

Cascades — SQLAlchemy 1.4 Documentation

Cascades Mappers support the concept of configurable cascade behavior on relationship() constructs. This refers to how operations performed on a “parent” object relative to a particular Session should be propagated to items referred to by that relation

docs.sqlalchemy.org