|
| 1 | +--- |
| 2 | +title: "RDB 정규화" |
| 3 | +description: "RDB 정규화 개념에 대해 설명합니다." |
| 4 | +date: 2025-08-07 +00:00:00 |
| 5 | +permalink: /posts/2025-08-07-db/ |
| 6 | +categories: [Blogging,db] |
| 7 | +--- |
| 8 | + |
| 9 | +관계형데이터베이스의 테이블을 효율적으로 설계하기위한 일련의 규칙, 즉 정규화를 말합니다. 데이터 중복을 최소화하고, 데이터 무결성을 향상시키며, 불필요한 데이터 변경을 방지하는것을 목표로 합니다. |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +일반적으로 3NF까지 도달하면 정규화가 됐다고 하고 있습니다. 이후 단계를 하는것은 복잡성이 증가하고 비효율적일 가능성이 높습니다. |
| 14 | + |
| 15 | +### 예제테이블 설명 |
| 16 | + |
| 17 | +수강신청한 학생, 강의, 교수의 정보를 담은 정규화 되지 않은 테이블을 만들어 생성합니다. |
| 18 | + |
| 19 | +```sql |
| 20 | +CREATE TABLE student_courses_0nf ( |
| 21 | + student_id INT, |
| 22 | + student_name VARCHAR(50), |
| 23 | + student_phone VARCHAR(20), |
| 24 | + student_major VARCHAR(50), |
| 25 | + course_id TEXT, |
| 26 | + course_name TEXT, |
| 27 | + professor TEXT, |
| 28 | + department TEXT, |
| 29 | + professor_phone TEXT, |
| 30 | + grade TEXT |
| 31 | +); |
| 32 | +``` |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | +### 1NF: 원자값 보장 |
| 37 | + |
| 38 | +수강신청한 `course_id` ,`course_name` , `professor` 들이 여러개의 값을 가지고 있습니다. 1NF는 이를 원자값으로 가지게하는 작업을 말합니다. |
| 39 | + |
| 40 | +```sql |
| 41 | +CREATE TABLE student_courses_1nf ( |
| 42 | + student_id INT, |
| 43 | + student_name VARCHAR(50), |
| 44 | + student_phone VARCHAR(20), |
| 45 | + student_major VARCHAR(50), |
| 46 | + course_id VARCHAR(10), |
| 47 | + course_name VARCHAR(50), |
| 48 | + professor VARCHAR(50), |
| 49 | + department VARCHAR(50), |
| 50 | + professor_phone VARCHAR(20), |
| 51 | + grade CHAR(1) |
| 52 | +); |
| 53 | +``` |
| 54 | + |
| 55 | + |
| 56 | + |
| 57 | +**1NF 문제점: 삽입/삭제/수정 이상** |
| 58 | + |
| 59 | +미적분학 김교수가 갑작스럽게 퇴직하여 다른 교수로 업데이트한다고 했을 때 강의를 듣는 김철수, 이영희 학생에 대한 ROW 2개를 업데이트를 하게됩니다. 이러한 과정에서 업데이트가 원활하게 이루어지지 않는다면 데이터 일관성이 깨지게 됩니다. |
| 60 | + |
| 61 | +### 2NF: 부분 함수 종속성 제거 |
| 62 | + |
| 63 | +현재 프라임키 `student_id` , `course_id` 에는 non-attribute key들이 부분 종속되어 있는걸 확인 할 수 있습니다. |
| 64 | + |
| 65 | +**부분 함수 종속 관계들:** |
| 66 | + |
| 67 | +- `student_name, student_phone` → `student_id` (student_id에만 종속) |
| 68 | +- `course_name, professor, department` → `course_id` (course_id에만 종속) |
| 69 | + |
| 70 | +**완전 함수 종속:** |
| 71 | + |
| 72 | +- `grade` → `(student_id, course_id)` (복합키 전체에 종속) |
| 73 | + |
| 74 | + |
| 75 | + |
| 76 | +```sql |
| 77 | +-- 학생 테이블 (student_id에만 종속되는 속성들) |
| 78 | +CREATE TABLE students_2nf ( |
| 79 | + student_id INT PRIMARY KEY, |
| 80 | + student_name VARCHAR(50), |
| 81 | + student_phone VARCHAR(20), |
| 82 | + student_major VARCHAR(50) |
| 83 | +); |
| 84 | + |
| 85 | +-- 과목 테이블 (course_id에만 종속되는 속성들) |
| 86 | +CREATE TABLE courses_2nf ( |
| 87 | + course_id VARCHAR(10) PRIMARY KEY, |
| 88 | + course_name VARCHAR(50), |
| 89 | + professor VARCHAR(50), |
| 90 | + department VARCHAR(50), |
| 91 | + professor_phone VARCHAR(20) |
| 92 | +); |
| 93 | + |
| 94 | +-- 수강 성적 테이블 (프라임키 전체에 종속되는 속성들) |
| 95 | +CREATE TABLE enrollments_2nf ( |
| 96 | + student_id INT, |
| 97 | + course_id VARCHAR(10), |
| 98 | + grade CHAR(1), |
| 99 | + PRIMARY KEY (student_id, course_id), |
| 100 | + FOREIGN KEY (student_id) REFERENCES students_2nf(student_id), |
| 101 | + FOREIGN KEY (course_id) REFERENCES courses_2nf(course_id) |
| 102 | +); |
| 103 | +``` |
| 104 | + |
| 105 | +**2NF문제점**: **이행적 함수 종속성** |
| 106 | + |
| 107 | +과목테이블의 기본키 `course_id` 가 `professor_phone` , `department` 결정되는게 아니라 교수의 이름 `professor` 이 `professor_phone` , `department` 결정하게 됩니다. |
| 108 | + |
| 109 | +> 🤔 이행적 함수 종속성이 뭔가요?\ |
| 110 | +> A → B, B → C 관계가 성립할 때, A → C가 성립하는걸 의미합니다.데이터 베이스에서는 기본키(A)가 아닌 일반 컬럼(B)이 다른 일반 컬럼(C)을 결저하는 것을 말합니다. |
| 111 | +
|
| 112 | +### 3NF: 이행적 함수 종속성 제거 |
| 113 | + |
| 114 | + |
| 115 | + |
| 116 | +```sql |
| 117 | +-- 교수 테이블 |
| 118 | +CREATE TABLE professors_3nf ( |
| 119 | + professor_name VARCHAR(50) PRIMARY KEY, |
| 120 | + professor_phone VARCHAR(20), |
| 121 | + department_name VARCHAR(50) |
| 122 | +); |
| 123 | + |
| 124 | +-- 과목 테이블 (3NF) |
| 125 | +CREATE TABLE courses_3nf ( |
| 126 | + course_id VARCHAR(10) PRIMARY KEY, |
| 127 | + course_name VARCHAR(50), |
| 128 | + professor_name VARCHAR(50), |
| 129 | + FOREIGN KEY (professor_name) REFERENCES professors_3nf(professor_name) |
| 130 | +); |
| 131 | + |
| 132 | +-- 학생 테이블 (변경 없음) |
| 133 | +CREATE TABLE students_3nf ( |
| 134 | + student_id INT PRIMARY KEY, |
| 135 | + student_name VARCHAR(50), |
| 136 | + student_phone VARCHAR(20), |
| 137 | + student_major VARCHAR(50) |
| 138 | +); |
| 139 | + |
| 140 | +-- 수강 성적 테이블 (변경 없음) |
| 141 | +CREATE TABLE enrollments_3nf ( |
| 142 | + student_id INT, |
| 143 | + course_id VARCHAR(10), |
| 144 | + grade CHAR(1), |
| 145 | + PRIMARY KEY (student_id, course_id), |
| 146 | + FOREIGN KEY (student_id) REFERENCES students_3nf(student_id), |
| 147 | + FOREIGN KEY (course_id) REFERENCES courses_3nf(course_id) |
| 148 | +); |
| 149 | +``` |
0 commit comments