정규형(normal form)은 표가 지켜야 할 조건의 단계입니다. 1정규형은 모든 값이 원자값이고, 2정규형은 여기서 부분 함수 종속을, 3정규형은 다시 이행 함수 종속을 없앤 표입니다.
이상 현상은 같은 값이 여러 곳에 되풀이되어 생겼습니다. 함수 종속은 어느 속성이 어느 속성을 정하는지 알려 줍니다. 이 둘을 이으면 표를 어디서 나눌지가 정해집니다. 문제를 만드는 화살표를 하나씩 골라 그 화살표를 따라 표를 나누는 일이 정규화입니다. 정규화는 단계마다 이름이 붙어 있고, 시험은 단계마다 무엇을 없애는지를 묻습니다.
그림은 함수 종속 레슨의 수강신청 표에서 학생 셋(101·102·104)을 씁니다. 아래 네 절이 그림의 단계 순서를 그대로 따라갑니다.
11정규형: 한 칸에 한 값
정규화 전 표에는 한 학생이 들은 과목 여러 개가 한 칸에 몰려 있습니다. 김민수의 과목 칸에는 'DS 자료구조 85, NW 네트워크 80, OS 운영체제 75'가 한꺼번에 들어 있습니다.
1정규형(1NF, First Normal Form)은 모든 속성의 값이 원자값(atomic value)인 표입니다. 원자값은 더 나눌 수 없는 값 하나입니다. 과목 칸을 과목코드·과목명·점수 세 열로 펼치고 과목마다 한 행으로 나누면 7행이 됩니다. 이제 한 행은 '학번 + 과목코드'로 구별됩니다. 자료에 따라 제1정규형처럼 앞에 '제'를 붙여 쓰기도 합니다.
22정규형: 부분 함수 종속 떼기
1정규형 표에는 함수 종속 레슨의 화살표가 그대로 있습니다. 점수는 기본키 전체에 완전 함수 종속입니다. 이름·학과코드는 학번에, 과목명은 과목코드에 부분 함수 종속입니다. 학과명은 학과코드를 거쳐 학번에 이행 함수 종속입니다. 부분과 이행 화살표가 김민수(3번)·'컴퓨터'(5번)·'운영체제'(3번)를 되풀이하게 만듭니다.
2정규형(2NF, Second Normal Form)은 1정규형이면서 부분 함수 종속을 없앤 표입니다. 키가 아닌 속성이 모두 기본키 전체에 완전 함수 종속이 됩니다. 학번에만 종속된 이름·학과코드·학과명을 학생 표로, 과목코드에만 종속된 과목명을 과목 표로 떼어 냅니다. 점수만 '학번 + 과목코드'에 남아 수강 표가 됩니다. 김민수와 '운영체제'는 한 번씩만 남습니다. 학생 표에는 이행 함수 종속이 남아 '컴퓨터'가 아직 두 번 적힙니다.
33정규형: 이행 함수 종속 떼기
3정규형(3NF, Third Normal Form)은 2정규형이면서 이행 함수 종속을 없앤 표입니다.
학생 표의 학번 → 학과코드 → 학과명에서 학과명을 학과코드와 함께 학과 표로 떼어 냅니다.
이제 '컴퓨터'도 한 번만 적힙니다.
이렇게 나온 학생·학과·과목·수강 네 표는 이 과목 예제 데이터의 네 표와 같은 구조입니다.
4다시 이으면 정보를 잃지 않는다
나눈 표를 학번·학과코드·과목코드 같은 값으로 다시 이으면 1정규형 표가 그대로 돌아옵니다. 정규화는 정보를 버리지 않고, 같은 사실을 한 곳에만 적도록 표를 나눕니다.
예제
단계마다 없앤 것과 나온 표를 정리하면 다음과 같습니다.
| 단계 | 없앤 것 | 나온 표 |
|---|---|---|
| 1정규형 | 한 칸에 든 여러 값 | 수강신청(학번, 과목코드, 이름, 학과코드, 학과명, 과목명, 점수) |
| 2정규형 | 부분 함수 종속 | 학생(학번, 이름, 학과코드, 학과명) · 과목(과목코드, 과목명) · 수강(학번, 과목코드, 점수) |
| 3정규형 | 이행 함수 종속 | 학생(학번, 이름, 학과코드) · 학과(학과코드, 학과명) · 과목(과목코드, 과목명) · 수강(학번, 과목코드, 점수) |
정말 정보를 잃지 않는지 돌려 봅니다. 예제 데이터의 네 표(학년·건물·학점·선수과목 열이 더 있습니다)를 다시 이어 수강신청 표의 일곱 열을 뽑으면 12행이 그대로 나옵니다.
SQL로 확인하기
조인(JOIN)은 관계대수의 ⋈처럼 두 표를 같은 값으로 이어 붙입니다. 학과가 없는 강도현(107)도 남기려고 학과는 LEFT JOIN으로 잇습니다. 조인의 종류는 14단원에서 배웁니다.
SELECT E.학번,
S.이름,
S.학과코드,
D.학과명,
E.과목코드,
C.과목명,
E.점수
FROM 수강 E
JOIN 학생 S
ON S.학번 = E.학번
LEFT JOIN 학과 D
ON D.학과코드 = S.학과코드
JOIN 과목 C
ON C.과목코드 = E.과목코드
ORDER BY E.학번,
E.과목코드;| 학번 | 이름 | 학과코드 | 학과명 | 과목코드 | 과목명 | 점수 |
|---|---|---|---|---|---|---|
| 101 | 김민수 | CS | 컴퓨터 | DS | 자료구조 | 85 |
| 101 | 김민수 | CS | 컴퓨터 | NW | 네트워크 | 80 |
| 101 | 김민수 | CS | 컴퓨터 | OS | 운영체제 | 75 |
| 102 | 이서준 | CS | 컴퓨터 | DS | 자료구조 | 70 |
| 102 | 이서준 | CS | 컴퓨터 | OS | 운영체제 | 60 |
| 103 | 김지민 | CS | 컴퓨터 | DS | 자료구조 | 65 |
| 103 | 김지민 | CS | 컴퓨터 | NW | 네트워크 | 55 |
| 104 | 박서연 | EE | 전자 | NW | 네트워크 | 95 |
| 104 | 박서연 | EE | 전자 | OS | 운영체제 | 75 |
| 105 | 최민준 | EE | 전자 | DS | 자료구조 | 100 |
| 105 | 최민준 | EE | 전자 | NW | 네트워크 | 90 |
| 107 | 강도현 | NULL | NULL | NW | 네트워크 | 50 |
수강신청 표 12행이 그대로 나왔습니다. '컴퓨터'는 이 결과에 7번 나오지만, 저장된 곳은 학과 표의 한 행뿐입니다. 대신 읽을 때마다 표 넷을 이어야 합니다. 이 부담을 덜려고 일부러 되돌리는 일은 반정규화 레슨에서 봅니다.
시험 포인트
- 필기: 1정규형은 원자값, 2정규형은 부분 함수 종속 제거, 3정규형은 이행 함수 종속 제거입니다. 다음 단계는 앞 단계를 만족한 위에서 하나를 더 없앱니다. 나눈 표를 다시 이으면 처음 정보가 그대로 돌아옵니다. 함수 종속이 주어진 표가 몇 정규형인지, 다음 단계에서 무엇을 없애는지를 묻습니다.
- 실기: 제1정규형(1NF, First Normal Form)·제2정규형(2NF, Second Normal Form)·제3정규형(3NF, Third Normal Form)·정규화(Normalization).
확인 문제
1. 네 표의 값은 모두 원자값입니다. 다음 가운데 2정규형은 만족하지만 3정규형은 아닌 것을 고르세요.
- ① 과목(과목코드, 과목명, 학점) — 기본키 과목코드
- ② 주문상세(주문번호, 상품번호, 주문자, 수량) — 기본키 '주문번호 + 상품번호', 주문자는 주문번호로 정해진다
- ③ 직원(사번, 이름, 직급코드, 직급명) — 기본키 사번, 직급명은 직급코드로 정해진다
- ④ 출석(사번, 날짜, 출근시각) — 기본키 '사번 + 날짜'
정답
③입니다. 기본키가 사번 하나라 부분 함수 종속이 없어 2정규형입니다. 그런데 사번 → 직급코드 → 직급명으로 직급명이 키가 아닌 직급코드를 거쳐 딸려 오므로 3정규형은 아닙니다.
- ① 같은 값이 여러 행에 보이면 3정규형이 아니라고 봤습니다. 학점 3이 여러 과목에 나오더라도, 학점은 과목코드가 정하는 값이라 떼어 낼 종속이 없습니다.
- ② 부분 함수 종속과 이행 함수 종속을 바꿔 봤습니다. 주문자는 기본키의 일부인 주문번호가 정하므로 부분 함수 종속이고, 이 표는 2정규형부터 아닙니다.
- ④ 기본키가 둘이면 아직 3정규형이 아니라고 봤습니다. 출근시각은 사번과 날짜를 함께 알아야 정해지고 다른 종속이 없어 3정규형입니다.
2. 다음 (가)~(라)에 맞는 이름을 쓰세요. (가)는 한글 이름과 영문으로, (나)~(라)는 한글 이름과 영문 약어로 함께 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.
- (가) 한 표에 여러 주제가 섞여 같은 값이 되풀이될 때, 주제마다 표를 나눠 같은 사실을 한 곳에만 적게 하는 일입니다.
- (나) 모든 칸에 더 나눌 수 없는 값 하나만 들어 있는 단계입니다.
- (다) (나)를 만족하면서, 기본키의 일부만으로 정해지는 속성을 떼어 낸 단계입니다.
- (라) (다)를 만족하면서, 키가 아닌 속성을 거쳐 딸려 오는 속성을 떼어 낸 단계입니다.
정답
받는 답: (가) 정규화(Normalization) · (나) 제1정규형(1NF) · (다) 제2정규형(2NF) · (라) 제3정규형(3NF)
(나)~(라)의 실마리는 단계마다 없애는 것입니다. 한 칸에 몰린 여러 값이면 (나), 기본키의 일부가 정하는 속성이면 (다), 키가 아닌 속성을 거쳐 딸려 오는 속성이면 (라)입니다.
- 같은 이름의 다른 꼴: 1정규형처럼 '제'를 뺀 꼴 — 자료에 따라 그렇게 쓰므로 함께 받습니다.
- 같은 이름의 다른 꼴: First Normal Form처럼 원어로 풀어 쓴 꼴 — 문제가 약어로 물었습니다.
- 틀리는 꼴 정규형 — (가)에: 표가 지켜야 할 조건의 단계를 가리키는 이름입니다. 표를 나누는 일 자체의 이름은 정규화입니다. Normalize처럼 품사를 바꿔 쓴 꼴도 받지 않습니다.
- 틀리는 꼴 제2정규형 — (라)에: 기본키의 일부가 정하는 속성을 떼어 낸 단계입니다. (라)는 키가 아닌 속성을 거치는 종속을 떼어 냅니다.
3. 예제의 조인 쿼리에서 학과를 잇는 LEFT JOIN을 JOIN으로 바꿔 행 수를 셌습니다. 결과는 몇 행이고, 어느 학생이 빠질까요?
SELECT COUNT(*) AS 행수
FROM 수강 E
JOIN 학생 S
ON S.학번 = E.학번
JOIN 학과 D
ON D.학과코드 = S.학과코드
JOIN 과목 C
ON C.과목코드 = E.과목코드;
정답
11행이고, 강도현(107)의 네트워크 행이 빠집니다.
| 행수 |
|---|
| 11 |
강도현은 학과코드가 NULL이라 학과 표에 짝지을 행이 없습니다. JOIN은 짝이 없는 행을 버리므로 12행 가운데 하나가 빠집니다.
나눈 표를 이으면 처음 표가 돌아온다는 것은 표를 올바르게 이었을 때의 이야기입니다. 값이 NULL인 쪽은 LEFT JOIN으로 남겨야 합니다.