함수 종속 :
X → Y는 “X가 정해지면 Y가 하나로 정해진다”는 의미
UNF_주문 (문제: 한 칸에 상품목록이 여러 개 들어감)
| 주문ID | 고객ID | 고객명 | 고객주소 | 상품목록(상품ID:수량) |
|---|---|---|---|---|
| O100 | C10 | 홍길동 | 서울 | P1:2, P2:1 |
| O101 | C11 | 김영희 | 부산 | P2:3 |
문제점
상품목록이 다중 값(리스트) → 1NF 위반상품목록을 행으로 풀어 주문-상품 라인 아이템 형태로 만든다.
1NF_주문라인(임시)
| 주문ID | 상품ID | 수량 | 고객ID | 고객명 | 고객주소 | 상품명 | 상품가격 |
|---|---|---|---|---|---|---|---|
| O100 | P1 | 2 | C10 | 홍길동 | 서울 | 아메리카노 | 3000 |
| O100 | P2 | 1 | C10 | 홍길동 | 서울 | 베이글 | 2500 |
| O101 | P2 | 3 | C11 | 김영희 | 부산 | 베이글 | 2500 |
키(Primary Key) 가정
(주문ID, 상품ID)로 잡으면 “한 주문에서 같은 상품은 한 번만 등장”한다고 가정할 수 있다.(주문ID, 상품ID) -> 수량주문ID → 고객ID, 고객명, 고객주소 주문ID(키 일부)에만 의존상품ID → 상품명, 상품가격 상품ID(키 일부)에만 의존즉 PK가 복합키 (주문ID, 상품ID)인데,
주문ID만으로 결정상품ID만으로 결정부분 종속되는 속성을 각각의 테이블로 분리한다.
(A) Orders_2NF (주문)
| 주문ID (PK) | 고객ID | 고객명 | 고객주소 |
|---|---|---|---|
| O100 | C10 | 홍길동 | 서울 |
| O101 | C11 | 김영희 | 부산 |
(B) Products_2NF (상품)
| 상품ID (PK) | 상품명 | 상품가격 |
|---|---|---|
| P1 | 아메리카노 | 3000 |
| P2 | 베이글 | 2500 |
(C) OrderItems_2NF (주문 상세)
| 주문ID (PK, FK) | 상품ID (PK, FK) | 수량 |
|---|---|---|
| O100 | P1 | 2 |
| O100 | P2 | 1 |
| O101 | P2 | 3 |
이제 상품명/가격은 Products로, 고객명/주소는 Orders로 이동하여 2NF 만족
2NF까지 끝냈는데도 Orders_2NF 안을 보면:
주문ID → 고객ID고객ID → 고객명, 고객주소 (고객ID가 고객 정보를 결정)주문ID → 고객명, 고객주소가 이행적(간접)으로 성립즉 주문ID → 고객ID → 고객명/주소 구조가 남아 있어 3NF 위반
고객 정보를 별도 테이블로 분리하고, 주문은 고객ID만 참조하도록 만듭니다.
(A) Customers_3NF (고객)
| 고객ID (PK) | 고객명 | 고객주소 |
|---|---|---|
| C10 | 홍길동 | 서울 |
| C11 | 김영희 | 부산 |
(B) Orders_3NF (주문)
| 주문ID (PK) | 고객ID (FK) |
|---|---|
| O100 | C10 |
| O101 | C11 |
(C) Products_3NF (상품) (2NF와 동일)
| 상품ID (PK) | 상품명 | 상품가격 |
|---|---|---|
| P1 | 아메리카노 | 3000 |
| P2 | 베이글 | 2500 |
(D) OrderItems_3NF (주문 상세) (2NF와 동일)
| 주문ID (PK, FK) | 상품ID (PK, FK) | 수량 |
|---|---|---|
| O100 | P1 | 2 |
| O100 | P2 | 1 |
| O101 | P2 | 3 |
이제 주문 테이블에는 “주문 자체”의 속성만 남고, 고객/상품 정보는 각 마스터 테이블에만 존재 → 3NF 만족한다.