ERD사용시 테이블 관계 연결할때 식별자와 비식별자 선택? 무슨 차이점이 있을까?

권수민·2023년 9월 8일
2
post-thumbnail

먼저 ERDcloud에 들어가서 로그인한 후 ERD를 만드는데!
팀이라면 권한을 주어 다같이 작성할 수 있게 된다!

그 이후에 ERD맨 오른쪽에 보면 설정칸이 있는데, 거기 눌러 들어가면

프로젝트 이름 및 테이블구조를 설정할 수 있는데 나는 논리+물리를 선택하고 domain과 type만 설정했다.

다 설정해주는게 여러모로 좋은것 같다는 생각은 작성후에 들기 시작했는데, 처음이라 설정할때 굳이 다 넣어줘야하나라고 생각했지만 생각보다 null값이 들어가는 데이터도 많고, 커멘트를 붙여줬는면 더 편하게 알아볼거 같다는 생각이 들었다.

테이블 구조

논리 테이블명 : 테이블명에 대한 설명 (한글)
물리 테이블명 : 실제 테이블명 (영문)
논리 필드명 : 필드명에 대한 설명 (한글)
물리 필드명 : 실제 필드명 (영문)
도메인 : 필드명에 대한 주제를 적는 곳 (이것도 일종의 코멘트와 같다)
타입 : int, varchar, date 필드 타입을 써주는 곳
NULL 유무 : NULL / NOT NULL 중에 하나
기본값 : default 값을 써주는 곳
코멘트 : 말 그대로 부가설명이 필요할 경우 써주는 곳이다
논리값은 그냥 주석, 부가설명 으로 이해하면 된다. 실제 쿼리에는 포함되지 않아 한글로 설명을 쓰면 된다.

여기서 이 관계도를 그리는 선에서 비식별자 관계인지 식별자 관계인지를 구분하라고 나왔을때, 이게 무슨뜻인가 했다.

Entity(테이블)간의 타입의 연결을 나타내는데 사용하는 방법으로,

  1. 식별관계 (Identifying Relationship):
  • 식별 관계는 부모 엔터티의 기본 키(PK, Primary Key)가 자식 엔터티의 기본 키로도 사용되는 관계
    =>이러한 관계에서 자식 엔터티는 부모 엔터티 없이는 존재할 수 없다.
  • ERD에서는 실선으로 표시되며, 자식 엔터티의 PK에 부모 엔터티의 PK가 포함되어 있음을 나타낸다.

풀이하자면, 한마디로 자식 PK가 FK로 그 부모의 PK를 받아오는것. 그렇게 되면 그 자식은 게시물로 예를 든다면 하나의 유저가 하나의 게시물만 작성하게되는것입니다. 1:N이 관계에서는 사용하면 안되는것이죠. OnetToOneField에서는 그래서 궅이 식별자로 나눌필요도 없게되는것인데. 말 그대로 부모의 PK를 받아오는 것이라 부모가 없으면 자식은 존재할 수 없습니다.

예)OneToOneField관계를 가진 user와 profile테이블의 관계

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    .
    .
    .

근데 굳이 저 primarykey를 넣어줘서 식별자로 만들 필요까지 있을까??
라는 생각을 해본다.

해줬을때 달라지는것은 pk가 user=pk를 가지게되는것과,
유저가 없으면 프로필이 없다는것인데....

profile_id데이터를 안넣어줘 메모리 세이브하는 정도의 이득이 있다 보지만...?
그렇게 크지도 않은 데이터를 위해 식별을 해줬다가
나중에 큰코! 다치는 일이있을수 있기때문에...

onotoone이라면 써도 되지만 그 외에는 식별 관계를 사용할지, 비식별 관계를 사용할지는
특정 애플리케이션의 요구사항, 데이터의 특성, 그리고 기대되는 확장성 등 여러 요소를 고려해야한다.

여기서 식별자를 사용하려할때 기본키를 고유하게 식별 할 수 있게 하기 위해서,
때로는 두개이상의 필드를 조합하여 복합 키(composite key) 를 기본 키로 사용한다.

PK는 오직 테이블 당 한개만 존재할 수 있다고 하였는데, 이 복합키로 두개의 pk를 가진다고 생각 하면 된다.
이렇게 만들어 주는 이유는 자식테이블이 부모테이블에 강하게 의존하는 경우를 강조할 때 사용하는것.

예: 주문(Order)과 주문 항목(Order Item) 간의 관계에서 주문 항목의 기본 키는 (Order ID, Item ID)와 같이 주문의 ID를 포함할 수 있습니다. 여기서 주문 항목은 주문 없이는 존재할 수 없으므로 식별 관계에 있습니다.

주문항복은 특정주문이 없이는 존재 할 수 없다.
주문은 외래키면서 동시에 복합 기본키의 일부로 주문항목은 복합 기본키의 다른부분입니다.

class Order(models.Model):
    order_id = models.AutoField(primary_key=True)
    order_date = models.DateTimeField(auto_now_add=True)

class OrderItem(models.Model):
    order = models.ForeignKey(Order, on_delete=models.CASCADE, primary_key=True)
    item_sequence = models.PositiveIntegerField()
    item_name = models.CharField(max_length=255)

    class Meta:
        unique_together = ('order', 'item_sequence')

Meta 클래스의 unique_together 옵션은 order와 item_sequence의 조합이 OrderItem 테이블에서 유일하게 유지되도록 한다.
이렇게 함으로써 OrderItem 테이블의 복합 기본 키를 구성하는것.

  1. 비식별 관계 (Non-Identifying Relationship):
  • 비식별자는 우리가 일반적으로 사용하는 방식의 관계로서,
  • 자식테이블의 기본키가 부모테이블의 기본키를 포함하지 않는 다는것.
    =>즉, 부모 테이블의 키본키는 외래키로만 사용되고, 자식테이블은 부모테이블과 독립적으로 존재할 수 있다.
  • ERD에서는 점선으로 표시.

예: 직원(Employee)과 부서(Department) 간의 관계에서 직원은 부서에 속할 수도 있고 속하지 않을 수도 있습니다. 여기서 직원의 기본 키는 직원 ID만을 포함하고, 부서는 외래 키로만 참조됩니다. 따라서 이는 비식별 관계에 있습니다.

from django.db import models

class Department(models.Model):
    department_name = models.CharField(max_length=255)

class Employee(models.Model):
    employee_name = models.CharField(max_length=255)
    department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True, blank=True)

추후 부서는 모델의 인스턴스로 생성해서

hr_department = Department(department_name="인사과")
hr_department.save()

support_department = Department(department_name="지원관")
support_department.save()

이렇게 저장해주면 된다.

profile
초보개발자

1개의 댓글

comment-user-thumbnail
2023년 9월 11일

ERD 작성이 처음엔 많이 어려웠을텐데 잘 정리해주었네요👍

답글 달기