데이터 연결 제거하기

데이터 연결 제거하기 (Remove Data Connections)

이번 장에서는 테이블과 테이블 사이의 연결을 끊는 방법을 배워요. 삭제가 아니라 연결만 제거하는 거예요.

출처: 공식문서

현재 데이터 상태

지금 우리는 team 테이블과 hero 테이블이 이렇게 연결되어 있어요.

team 테이블:

id name headquarters
1 Preventers Sharp Tower
2 Z-Force Sister Margaret's Bar

hero 테이블:

id name secret_name age team_id
1 Deadpond Dive Wilson null 2
2 Rusty-Man Tommy Sharp 48 1
3 Spider-Boy Pedro Parqueador null 1

이전 장에서 Spider-Boy를 Preventers 팀에 넣어서 team_id1이 됐죠. 이제 이 행들 사이의 연결을 어떻게 제거하는지 볼 거예요.

이전 장의 코드를 이어서 사용할게요.

from sqlmodel import Field, Session, SQLModel, create_engine


class Team(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    headquarters: str


class Hero(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    secret_name: str
    age: int | None = Field(default=None, index=True)

    team_id: int | None = Field(default=None, foreign_key="team.id")


sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"

engine = create_engine(sqlite_url, echo=True)


def create_db_and_tables():
    SQLModel.metadata.create_all(engine)


def create_heroes():
    with Session(engine) as session:
        team_preventers = Team(name="Preventers", headquarters="Sharp Tower")
        team_z_force = Team(name="Z-Force", headquarters="Sister Margaret's Bar")
        session.add(team_preventers)
        session.add(team_z_force)
        session.commit()

        hero_deadpond = Hero(
            name="Deadpond", secret_name="Dive Wilson", team_id=team_z_force.id
        )
        hero_rusty_man = Hero(
            name="Rusty-Man",
            secret_name="Tommy Sharp",
            age=48,
            team_id=team_preventers.id,
        )
        hero_spider_boy = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
        session.add(hero_deadpond)
        session.add(hero_rusty_man)
        session.add(hero_spider_boy)
        session.commit()

        session.refresh(hero_deadpond)
        session.refresh(hero_rusty_man)
        session.refresh(hero_spider_boy)

        print("Created hero:", hero_deadpond)
        print("Created hero:", hero_rusty_man)
        print("Created hero:", hero_spider_boy)

        hero_spider_boy.team_id = team_preventers.id
        session.add(hero_spider_boy)
        session.commit()
        session.refresh(hero_spider_boy)
        print("Updated hero:", hero_spider_boy)


def main():
    create_db_and_tables()
    create_heroes()


if __name__ == "__main__":
    main()

연결 끊기

연결을 끊기 위해 애써 뭔가를 삭제할 필요는 없어요. 외래 키에, 여기서는 team_id에 그냥 None을 할당하면 됩니다.

Spider-Boy가 이웃이 없어서 지쳤다고 해볼게요. 그는 Preventers에서 나가고 싶어해요. 단순히 team_idNone으로 설정하면 팀과의 연결이 사라집니다.

# Code above omitted 👆

def create_heroes():
    with Session(engine) as session:
        # Code here omitted 👈

        hero_spider_boy.team_id = None
        session.add(hero_spider_boy)
        session.commit()
        session.refresh(hero_spider_boy)
        print("No longer Preventer:", hero_spider_boy)

        # Code below omitted 👇

여기서도 우리는 그저 team_id 필드 속성에 값을 할당했을 뿐이에요. 이번에는 값이 None이라서, 데이터베이스에서는 NULL을 의미해요. 그런 다음 히어로를 세션에 add() 하고 commit() 했어요.

이어서 refresh() 로 최신 데이터를 가져와 출력합니다.

명령줄에서 실행하면 이렇게 출력됩니다.

$ uv run python app.py

// Previous output omitted 😉

// Update the hero
INFO Engine UPDATE hero SET team_id=? WHERE hero.id = ?
INFO Engine [cached since 0.07753s ago] (None, 3)
// Commit the session
INFO Engine COMMIT
// Automatically start a new transaction
INFO Engine BEGIN (implicit)
// Refresh the hero
INFO Engine SELECT hero.id, hero.name, hero.secret_name, hero.age, hero.team_id
FROM hero
WHERE hero.id = ?
INFO Engine [cached since 0.1661s ago] (3,)

// Print the hero without a team
No longer Preventer: id=3 secret_name='Pedro Parqueador' team_id=None name='Spider-Boy' age=None

이제 Spider-Boy는 team_id=None이라 어떤 팀에도 연결되지 않았어요. 💥

정리하면, 서로 다른 테이블의 행 사이 연결을 끊으려면 외래 키 컬럼의 값을 해제(여기선 None)하면 그만입니다.

더 알아보기 (Learn more)