DevLearn logo
Skill Up With Me
Interactive Learning
Signing in…

Нормализация данных: 1НФ, 2НФ, 3НФ

🔒 Sign in to use this
Нормализация: Наводим порядок в данных

Представьте таблицу университета, где в одной ячейке через запятую перечислены все курсы студента, а рядом смешаны телефон и адрес. Если человек сменит фамилию или переедет, эту цепочку придётся искать и править во множестве мест. Нормализация — это осознанное разбиение данных на таблицы и связи, чтобы убрать дубли, предотвратить противоречия и упростить сопровождение базы.

Зачем это нужно? Три класса аномалий
Откройте карточку — что ломается без нормализации
Аномалия вставки
🗑️
Аномалия удаления
✏️
Аномалия обновления
Путь нормализации: 1НФ → 2НФ → 3НФ
Нажимайте шаги — порядок декомпозиции
1️⃣
1НФ
Атомарность — убираем списки в ячейках
2️⃣
2НФ
Весь ключ — убираем частичные зависимости
3️⃣
3НФ
Только от ключа — убираем транзитивные зависимости
Первая нормальная форма (1НФ)

Правило 1НФ простое: в каждой ячейке — одно неделимое значение из домена. Никаких «списков через запятую» в одном поле: для этого есть отдельные строки или отдельная таблица.

Исправление 1НФ — вариант «до»
sql
1
-- Плохо: нарушение 1НФ — несколько телефонов в одной ячейке
2
CREATE TABLE students_bad (
3
    id          SERIAL PRIMARY KEY,
4
    full_name   TEXT NOT NULL,
5
    phones      TEXT  -- '+7999..., +7911...'
6
);
Исправление 1НФ — вариант «после»
sql
1
-- Хорошо: 1НФ — один телефон на строку
2
CREATE TABLE students (
3
    id        SERIAL PRIMARY KEY,
4
    full_name TEXT NOT NULL
5
);
6
CREATE TABLE student_phones (
7
    id         SERIAL PRIMARY KEY,
8
    student_id INT NOT NULL REFERENCES students(id),
9
    phone      TEXT NOT NULL
10
);
Вторая нормальная форма (2НФ)

2НФ актуальна при составном первичном ключе. Каждый неключевой атрибут должен зависеть от всего ключа целиком, а не от его части. Если ключ — пара «студент + курс», то длительность курса зависит только от курса: хранить её в строке зачисления значит копировать одно и то же и рисковать рассинхроном.

Исправление 2НФ — вариант «до»
sql
1
-- Плохо: частичная зависимость от составного ключа
2
CREATE TABLE enrollments_bad (
3
    student_id   INT NOT NULL,
4
    course_id    INT NOT NULL,
5
    enrolled_at  DATE NOT NULL,
6
    course_duration_hours INT NOT NULL, -- дубли на каждого студента
7
    PRIMARY KEY (student_id, course_id)
8
);
Исправление 2НФ — вариант «после»
sql
1
-- Хорошо: длительность хранится один раз, в каталоге курсов
2
CREATE TABLE courses (
3
    id          SERIAL PRIMARY KEY,
4
    title       TEXT NOT NULL,
5
    duration_hours INT NOT NULL
6
);
7
CREATE TABLE enrollments (
8
    student_id  INT NOT NULL,
9
    course_id   INT NOT NULL REFERENCES courses(id),
10
    enrolled_at DATE NOT NULL,
11
    PRIMARY KEY (student_id, course_id)
12
);
Третья нормальная форма (3НФ)

3НФ запрещает транзитивные зависимости: неключевой столбец не должен зависеть от другого неключевого столбца. Если у студента есть `city_id` и рядом дублируется `city_name`, имя города зависит от идентификатора города, а не от первичного ключа студента. Имя нужно хранить в отдельном справочнике.

Исправление 3НФ — вариант «до»
sql
1
-- Плохо: city_name транзитивно зависит от city_id, а не от id студента
2
CREATE TABLE students_bad_city (
3
    id         SERIAL PRIMARY KEY,
4
    full_name  TEXT NOT NULL,
5
    city_id    INT NOT NULL,
6
    city_name  TEXT NOT NULL  -- дублируем справочник
7
);
Исправление 3НФ — вариант «после»
sql
1
-- Хорошо: справочник городов, у студента только city_id
2
CREATE TABLE cities (
3
    id        SERIAL PRIMARY KEY,
4
    name      TEXT NOT NULL
5
);
6
CREATE TABLE students (
7
    id        SERIAL PRIMARY KEY,
8
    full_name TEXT NOT NULL,
9
    city_id   INT NOT NULL REFERENCES cities(id)
10
);
Шпаргалка

1НФ • 2НФ • 3НФ — в одном взгляде

Нормализация — не религия и не беспредельное дробление: это снятие избыточности до уровня, где аномалии вставки, удаления и обновления перестают угрожать данным. Для учебных OLTP-схем 3НФ часто разумная отправная точка.
1НФ: не делимое значение в ячейке
2НФ: неключевые атрибуты зависят от всего первичного ключа
3НФ: неключевые атрибуты зависят только от ключа, не друг от друга
Нет лишних дублей — меньше расхождений и проще сопровождение
🔒 Sign in to use this