Назови три нормальные формы в SQL

«Назови три нормальные формы в SQL» — вопрос из категории Базы данных, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

1. Первая нормальная форма (1NF) Таблица находится в 1NF, если:

  • Все значения атрибутов атомарны (неделимы). Нет составных значений, массивов или списков в одной ячейке.
  • Нет повторяющихся групп столбцов.
  • Определён первичный ключ (явно или неявно).

Пример нарушения и исправления:

-- НАРУШЕНИЕ 1NF: неатомарное значение, список в одной ячейке
CREATE TABLE Orders (
    order_id INT PRIMARY KEY,
    customer_name VARCHAR(100),
    items VARCHAR(500) -- Например: 'Laptop, Mouse, Keyboard'
);

-- СООТВЕТСТВИЕ 1NF: каждая сущность в отдельной строке
CREATE TABLE OrderItems (
    order_id INT,
    item_name VARCHAR(100),
    quantity INT,
    PRIMARY KEY (order_id, item_name),
    FOREIGN KEY (order_id) REFERENCES Orders(order_id)
);
-- Данные: (1, 'Laptop', 1), (1, 'Mouse', 1), (1, 'Keyboard', 1)

2. Вторая нормальная форма (2NF) Таблица находится в 2NF, если:

  • Она уже в 1NF.
  • Все неключевые атрибуты полностью функционально зависят от всего составного первичного ключа (нет частичных зависимостей).

Пример нарушения и исправления:

-- НАРУШЕНИЕ 2NF: цена зависит только от product_id, а не от пары (order_id, product_id)
CREATE TABLE OrderDetails (
    order_id INT,
    product_id INT,
    product_name VARCHAR(100), -- Частичная зависимость: зависит только от product_id
    price DECIMAL(10,2),      -- Частичная зависимость: зависит только от product_id
    quantity INT,
    PRIMARY KEY (order_id, product_id)
);

-- СООТВЕТСТВИЕ 2NF: выносим частичные зависимости в отдельную таблицу
CREATE TABLE Products (
    product_id INT PRIMARY KEY,
    product_name VARCHAR(100),
    price DECIMAL(10,2)
);

CREATE TABLE OrderDetails (
    order_id INT,
    product_id INT,
    quantity INT,
    PRIMARY KEY (order_id, product_id),
    FOREIGN KEY (product_id) REFERENCES Products(product_id)
);

3. Третья нормальная форма (3NF) Таблица находится в 3NF, если:

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

Пример нарушения и исправления:

-- НАРУШЕНИЕ 3NF: manager зависит от department, а не напрямую от emp_id (транзитивная зависимость)
CREATE TABLE Employees (
    emp_id INT PRIMARY KEY,
    emp_name VARCHAR(100),
    department VARCHAR(50),
    department_manager VARCHAR(100) -- Зависит от department, а не от emp_id
);

-- СООТВЕТСТВИЕ 3NF: выносим транзитивную зависимость
CREATE TABLE Departments (
    department_name VARCHAR(50) PRIMARY KEY,
    manager VARCHAR(100)
);

CREATE TABLE Employees (
    emp_id INT PRIMARY KEY,
    emp_name VARCHAR(100),
    department VARCHAR(50),
    FOREIGN KEY (department) REFERENCES Departments(department_name)
);

Практический итог: Нормализация уменьшает избыточность данных и аномалии при вставке, обновлении и удалении, но может увеличивать количество JOIN-запросов. Часто идут на компромисс, денормализируя таблицы для производительности на чтение в аналитических системах (OLAP).