← Назад к вопросам

Расскажи о третьей нормальной форме базы данных

2.2 Middle🔥 171 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Третья нормальная форма (3NF) базы данных

Третья нормальная форма (3NF) — это уровень нормализации схемы БД, который обеспечивает минимальную избыточность данных при сохранении возможности эффективного выполнения запросов. 3NF считается стандартом для большинства операционных баз данных.

Условия для 3NF

Таблица находится в 3NF, если она:

  1. Находится в 2NF — все неключевые атрибуты полностью зависят от первичного ключа (не только частью)
  2. Не содержит транзитивных зависимостей — неключевые атрибуты не зависят друг от друга, только от первичного ключа

Главное правило 3NF: "Неключевой атрибут должен зависеть только от первичного ключа, ничего кроме первичного ключа и ничего, кроме первичного ключа"

Пример нарушения 3NF

Таблица без 3NF (имеет транзитивную зависимость):

Таблица Students:
┌──────────┬──────────┬────────────┬──────────────┐
│ student_id │ name   │ city_id    │ city_name    │
├──────────┼──────────┼────────────┼──────────────┤
│ 1        │ Иван    │ 10         │ Москва       │
│ 2        │ Петр    │ 10         │ Москва       │
│ 3        │ Мария   │ 20         │ Санкт-Петербург │
└──────────┴──────────┴────────────┴──────────────┘

Проблема: city_name зависит от city_id, а не напрямую от student_id. Это транзитивная зависимость.

  • Если изменить название города, придётся обновлять несколько строк
  • Если удалить все студентов из города, потеряем информацию о самом городе
  • Дублирование данных (город повторяется много раз)

Преобразование в 3NF

Разделяем на две таблицы:

// Таблица 1: Students (содержит только прямые зависимости от PK)
Таблица Students:
┌──────────┬──────────┬────────────┐
│ student_id │ name   │ city_id    │
├──────────┼──────────┼────────────┤
│ 1        │ Иван    │ 10         │
│ 2        │ Петр    │ 10         │
│ 3        │ Мария   │ 20         │
└──────────┴──────────┴────────────┘

// Таблица 2: Cities (город и его свойства)
Таблица Cities:
┌──────────┬────────────────────┐
│ city_id  │ city_name          │
├──────────┼────────────────────┤
│ 10       │ Москва             │
│ 20       │ Санкт-Петербург    │
└──────────┴────────────────────┘

Теперь каждая таблица в 3NF: каждый неключевой атрибут зависит только от первичного ключа.

Пример с покупками

Нарушение 3NF:

Таблица Orders (содержит транзитивные зависимости):
┌──────────┬────────────┬──────────┬─────────────────┬──────────────┐
│ order_id │ customer_id │ product_id │ product_name  │ category     │
├──────────┼────────────┼──────────┼─────────────────┼──────────────┤
│ 101      │ 1          │ 200      │ Ноутбук       │ Электроника  │
│ 102      │ 2          │ 200      │ Ноутбук       │ Электроника  │
│ 103      │ 1          │ 300      │ Монитор       │ Электроника  │
└──────────┴────────────┴──────────┴─────────────────┴──────────────┘

Проблемы:

  • product_name и category зависят от product_id, а не от order_id
  • Дублирование названий товаров и категорий

Коррекция в 3NF:

// Таблица Orders (только direct dependencies)
Таблица Orders:
┌──────────┬────────────┬──────────┐
│ order_id │ customer_id │ product_id │
├──────────┼────────────┼──────────┤
│ 1011200      │
│ 1022200      │
│ 1031300      │
└──────────┴────────────┴──────────┘

// Таблица Products (продукт и его свойства)
Таблица Products:
┌──────────┬──────────────┬──────────────┐
│ product_id │ product_name │ category   │
├──────────┼──────────────┼──────────────┤
│ 200      │ Ноутбук     │ Электроника  │
│ 300      │ Монитор     │ Электроника  │
└──────────┴──────────────┴──────────────┘

Сравнение нормальных форм

1NF — Исходная форма
↓ Устраняем частичные зависимости
2NF — Вторая нормальная форма
↓ Устраняем транзитивные зависимости
3NF — Третья нормальная форма ✓
↓ (редко используется)
BCNF — Нормальная форма Бойса-Кодда

Практический пример на Java/Hibernate

// Класс без 3NF (содержит лишнюю информацию)
@Entity
public class Order {
    @Id
    private Long orderId;
    
    @ManyToOne
    @JoinColumn(name = "customer_id")
    private Customer customer;
    
    @ManyToOne
    @JoinColumn(name = "product_id")
    private Product product;
    
    // Лишнее! product_name и category уже в Product
    private String productName;      // Транзитивная зависимость
    private String productCategory;  // Транзитивная зависимость
}

// Правильная реализация в 3NF
@Entity
public class Order {
    @Id
    private Long orderId;
    
    @ManyToOne
    @JoinColumn(name = "customer_id")
    private Customer customer;
    
    @ManyToOne
    @JoinColumn(name = "product_id")
    private Product product;
    // Никаких дублей информации о product
}

@Entity
public class Product {
    @Id
    private Long productId;
    
    private String productName;
    private String category;
}

Преимущества 3NF

  • Минимальная избыточность — каждый атрибут хранится один раз
  • Целостность данных — нет аномалий обновления и удаления
  • Эффективность операций — правильно спроектирована для большинства операций
  • Гибкость — легче добавлять новые свойства сущностей

Недостатки 3NF

  • Больше JOIN'ов — при получении связанных данных нужны соединения таблиц
  • Сложнее запросы — требуются более сложные SELECT'ы
  • Производительность — для OLAP систем может быть медленнее

Для систем, требующих высокой производительности чтения, используют денормализацию и хранилища данных (Data Warehouse), но для операционных OLTP систем 3NF остаётся золотым стандартом.

Расскажи о третьей нормальной форме базы данных | PrepBro