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

Сколько существует нормальных форм?

1.3 Junior🔥 121 комментариев
#Базы данных и SQL

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

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

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

Нормальные формы в реляционных БД

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

Определение и цель

Нормальная форма — это набор требований к структуре таблиц, которые исключают:

  • Дублирование данных
  • Аномалии при обновлении
  • Потерю информации при удалении
  • Избыточное хранение информации

Иерархия нормальных форм

Существует пять основных нормальных форм плюс дополнительные: BCNF (Boyce-Codd Normal Form).

Нулевая норм. форма (UNF — Unnormalized Form)

Данные без какой-либо нормализации:

-- Ненормализованная таблица (с повторяющимися группами)
CREATE TABLE Orders (
    OrderID INT PRIMARY KEY,
    CustomerName VARCHAR(100),
    Products VARCHAR(500),  -- Список товаров в одной ячейке
    Quantities VARCHAR(500)  -- Список количеств
);

-- Пример данных:
Insert INTO Orders VALUES
(1, 'John Smith', 'Laptop, Mouse, Keyboard', '1, 2, 3');
-- Товары хранятся в одной ячейке - это источник проблем

Проблемы:

  • Сложный парсинг данных
  • Аномалии обновления
  • Сложные запросы

Первая нормальная форма (1NF)

Правило: Каждое поле должно содержать атомарное значение (не делимое). Не должно быть повторяющихся групп.

-- Нормализация до 1NF
CREATE TABLE Orders (
    OrderID INT,
    CustomerName VARCHAR(100),
    PRIMARY KEY(OrderID)
);

CREATE TABLE OrderItems (
    OrderID INT,
    ItemIndex INT,
    ProductName VARCHAR(100),
    Quantity INT,
    PRIMARY KEY(OrderID, ItemIndex),
    FOREIGN KEY(OrderID) REFERENCES Orders(OrderID)
);

-- Данные теперь разделены:
Insert INTO Orders VALUES (1, 'John Smith');
Insert INTO OrderItems VALUES (1, 1, 'Laptop', 1);
Insert INTO OrderItems VALUES (1, 2, 'Mouse', 2);
Insert INTO OrderItems VALUES (1, 3, 'Keyboard', 3);

Выгода: Легко добавлять/изменять товары.

Вторая нормальная форма (2NF)

Правило: Таблица в 1NF, плюс все неключевые атрибуты полностью зависят от первичного ключа. Нет частичных зависимостей.

-- Ненормализованная таблица
CREATE TABLE StudentCourses (
    StudentID INT,
    CourseID INT,
    StudentName VARCHAR(100),  -- Зависит ТОЛЬКО от StudentID
    CourseName VARCHAR(100),   -- Зависит ТОЛЬКО от CourseID
    Grade CHAR(1),             -- Зависит от ОБОИХ
    PRIMARY KEY(StudentID, CourseID)
);
-- Проблема: StudentName зависит только от StudentID, не от всего ключа

-- Нормализация до 2NF
CREATE TABLE Students (
    StudentID INT PRIMARY KEY,
    StudentName VARCHAR(100)
);

CREATE TABLE Courses (
    CourseID INT PRIMARY KEY,
    CourseName VARCHAR(100)
);

CREATE TABLE Enrollment (
    StudentID INT,
    CourseID INT,
    Grade CHAR(1),
    PRIMARY KEY(StudentID, CourseID),
    FOREIGN KEY(StudentID) REFERENCES Students(StudentID),
    FOREIGN KEY(CourseID) REFERENCES Courses(CourseID)
);
-- Grade зависит от обоих полей ключа - это нормально

Выгода: Исключены аномалии обновления (не нужно обновлять StudentName в нескольких местах).

Третья нормальная форма (3NF)

Правило: Таблица в 2NF, плюс все неключевые атрибуты зависят напрямую только от первичного ключа. Нет транзитивных зависимостей.

-- Ненормализованная таблица с транзитивной зависимостью
CREATE TABLE Employees (
    EmployeeID INT PRIMARY KEY,
    EmployeeName VARCHAR(100),
    DepartmentID INT,
    DepartmentName VARCHAR(100),  -- Зависит от DepartmentID, а не от EmployeeID
    ManagerID INT,
    ManagerName VARCHAR(100)       -- Зависит от ManagerID, а не от EmployeeID
);
-- Проблема: DepartmentName и ManagerName - косвенные зависимости

-- Нормализация до 3NF
CREATE TABLE Departments (
    DepartmentID INT PRIMARY KEY,
    DepartmentName VARCHAR(100)
);

CREATE TABLE Managers (
    ManagerID INT PRIMARY KEY,
    ManagerName VARCHAR(100)
);

CREATE TABLE Employees (
    EmployeeID INT PRIMARY KEY,
    EmployeeName VARCHAR(100),
    DepartmentID INT,
    ManagerID INT,
    FOREIGN KEY(DepartmentID) REFERENCES Departments(DepartmentID),
    FOREIGN KEY(ManagerID) REFERENCES Managers(ManagerID)
);
-- Все атрибуты теперь зависят прямо от EmployeeID

Выгода: Устранены аномалии (изменение имени департамента в одном месте).

Нормальная форма Бойса-Кодда (BCNF)

Правило: Более строгая версия 3NF. Каждый детерминант должен быть候選 ключом (candidate key).

-- Пример нарушения BCNF
CREATE TABLE Professors (
    ProfessorID INT,
    SubjectID INT,
    TimeSlot VARCHAR(20),
    PRIMARY KEY(ProfessorID, SubjectID)
);
-- Если один профессор может преподавать только один предмет,
-- то TimeSlot зависит только от ProfessorID, а не от ключа в целом

-- BCNF нормализация
CREATE TABLE ProfessorSubjects (
    ProfessorID INT,
    SubjectID INT,
    PRIMARY KEY(ProfessorID, SubjectID),
    UNIQUE(ProfessorID, SubjectID)
);

CREATE TABLE ProfessorSchedules (
    ProfessorID INT PRIMARY KEY,
    TimeSlot VARCHAR(20),
    FOREIGN KEY(ProfessorID) REFERENCES ProfessorSubjects(ProfessorID)
);

Четвёртая нормальная форма (4NF)

Правило: BCNF, плюс нет не-функциональных зависимостей (многозначных зависимостей).

-- Нарушение 4NF: многозначные зависимости
CREATE TABLE CourseInstructor (
    CourseID INT,
    InstructorID INT,
    TextbookID INT,
    PRIMARY KEY(CourseID, InstructorID, TextbookID)
);
-- Проблема: если курс может иметь МНОГО инструкторов
-- И МНОГО учебников независимо друг от друга,
-- это многозначная зависимость

-- 4NF нормализация
CREATE TABLE CourseInstructors (
    CourseID INT,
    InstructorID INT,
    PRIMARY KEY(CourseID, InstructorID)
);

CREATE TABLE CourseTextbooks (
    CourseID INT,
    TextbookID INT,
    PRIMARY KEY(CourseID, TextbookID)
);
-- Теперь инструкторы и учебники разделены

Пятая нормальная форма (5NF)

Правило: Также называется PJNF (Project-Join Normal Form). Не должно быть циклических зависимостей на уровне проекции и соединения.

-- Очень редкий случай в практической разработке
-- Используется для сложных отношений в аналитических системах

Сравнительная таблица

┌────────┬────────────────────────────────────────────────────────┐
│   NF   │ Требования                                             │
├────────┼────────────────────────────────────────────────────────┤
│  UNF   │ Повторяющиеся группы разрешены                        │
│  1NF   │ Только атомарные значения                             │
│  2NF   │ 1NF + нет частичных зависимостей от ключа            │
│  3NF   │ 2NF + нет транзитивных зависимостей                  │
│ BCNF   │ Строже чем 3NF: каждый детерминант = кандидат ключа  │
│  4NF   │ BCNF + нет многозначных зависимостей                 │
│  5NF   │ 4NF + нет циклических зависимостей                   │
└────────┴────────────────────────────────────────────────────────┘

Денормализация: когда нарушать правила

-- Иногда денормализация необходима для производительности
CREATE TABLE Orders (
    OrderID INT PRIMARY KEY,
    CustomerID INT,
    CustomerName VARCHAR(100),     -- Денормализация
    CustomerEmail VARCHAR(100),    -- Денормализация
    TotalAmount DECIMAL(10, 2),    -- Кэшированное значение
    FOREIGN KEY(CustomerID) REFERENCES Customers(CustomerID)
);
-- Копируем CustomerName и Email для быстрого доступа без JOIN

Когда денормализировать:

  • Критическая важность производительности
  • Часто используемые одинаковые JOIN'ы
  • Кэширование вычисленных значений
  • Data Warehouse и аналитические БД

Практический подход

  1. Начни с 3NF — это оптимум для большинства приложений
  2. Тесты производительности — если медленно, рассмотри денормализацию
  3. Редко нужны 4NF и 5NF — используются в специальных случаях
  4. Документируй решения — почему денормализовано

Резюме

Существует пять основных нормальных форм плюс BCNF:

  1. 1NF — только атомарные значения
  2. 2NF — нет частичных зависимостей
  3. 3NF — нет транзитивных зависимостей (используется в 99% случаев)
  4. BCNF — каждый детерминант = кандидат ключа
  5. 4NF — нет многозначных зависимостей
  6. 5NF — нет циклических зависимостей

Для практической разработки 3NF обычно достаточно, более высокие формы используются редко и в специализированных случаях.