Что такое нормальная форма в контексте баз данных?

Ответ

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

Каждая последующая нормальная форма включает требования предыдущих и добавляет новые, более строгие ограничения.

Краткий обзор ключевых нормальных форм:

НФ Требование Простая проверка
1NF Атомарность атрибутов, отсутствие повторяющихся групп. Все ли значения в столбцах неделимы? Нет ли списков или массивов в одной ячейке?
2NF Находится в 1NF. Нет частичных зависимостей неключевых атрибутов от составного первичного ключа. Если PK составной, зависит ли каждый неключевой атрибут от ВСЕХ частей PK, а не от какой-то одной?
3NF Находится в 2NF. Нет транзитивных зависимостей (неключевые атрибуты зависят только от PK, а не друг от друга). Можно ли вывести значение одного неключевого атрибута из другого неключевого? Если да — нарушение 3NF.
BCNF (Бойса-Кодда) Усиленная 3NF. Каждый детерминант (атрибут, от которого функционально зависит другой атрибут) должен быть потенциальным ключом. Для всех зависимостей X → Y, является ли X суперключом?

Практический пример нарушения 1NF и его исправление:

-- Нарушение 1NF: столбец 'Phones' содержит составные данные (список).
CREATE TABLE Customer (
    CustomerID INT PRIMARY KEY,
    Name VARCHAR(100),
    Phones VARCHAR(200) -- Например: '+79161234567, +74951234567'
);
-- Соответствие 1NF: каждый телефон на отдельной строке.
CREATE TABLE Customer (
    CustomerID INT PRIMARY KEY,
    Name VARCHAR(100)
);
CREATE TABLE CustomerPhone (
    CustomerID INT,
    PhoneNumber VARCHAR(20),
    PRIMARY KEY (CustomerID, PhoneNumber),
    FOREIGN KEY (CustomerID) REFERENCES Customer(CustomerID)
);

Следование нормальным формам — фундамент для создания устойчивых, легко поддерживаемых и масштабируемых схем данных.

Ответ 18+ 🔞

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

Нормальная форма (НФ) — это, по сути, свод законов для твоих табличек. Если их соблюдать, данные не будут повторяться как последний мат по ТВ, и не случится такого, что ты одно поменял, а в другом месте осталась старая хуйня. Каждая следующая форма — это новый уровень строгости, как в армии.

Краткая шпаргалка, чтобы не еб*ть мозг:

НФ Суть требования Как проверить на своей шкуре?
1NF Всё должно быть по полочкам. Никаких списков в одной ячейке! В столбце «Телефоны» у тебя запись «+7916..., +7495...»? Поздравляю, ты мудак. Надо каждому номеру — свою строчку.
2NF Уже в 1NF. Если ключ составной (из нескольких полей), то все остальные поля должны зависеть от ВСЕГО ключа, а не кусками. Есть таблица «Заказ-Товар» (ID заказа + ID товара = ключ). Поле «Название товара» зависит только от ID товара, а не от всей пары ключей? Нарушение, дружок. Выноси товары в отдельную таблицу.
3NF Уже в 2NF. Все неключевые поля должны зависеть ТОЛЬКО от первичного ключа, а не друг от друга. В таблице «Сотрудник» есть поля: ID, Отдел, Телефон_отдела. Телефон отдела зависит от отдела, а не от ID сотрудника. Вот это транзитивная зависимость, и она тут лишняя. Отделы — в свою таблицу.
BCNF Усиленная 3NF. Каждый определяющий атрибут (детерминант) должен быть ключом. Сложная хуйня, но если коротко: если у тебя поле А определяет поле Б, то А должно быть уникальным ключом. Иначе — пиздец и разделение таблиц.

Пример из жизни, как нарушают первую форму:

-- Так делать — пиздец как неправильно. Кто так хранит телефоны? Идиот.
CREATE TABLE Customer (
    CustomerID INT PRIMARY KEY,
    Name VARCHAR(100),
    Phones VARCHAR(200) -- Типа: '+79161234567, +74951234567'
);
-- А вот так — уже человек с головой. Чисто, аккуратно, можно спать спокойно.
CREATE TABLE Customer (
    CustomerID INT PRIMARY KEY,
    Name VARCHAR(100)
);
CREATE TABLE CustomerPhone (
    CustomerID INT,
    PhoneNumber VARCHAR(20),
    PRIMARY KEY (CustomerID, PhoneNumber),
    FOREIGN KEY (CustomerID) REFERENCES Customer(CustomerID)
);

Если будешь этим правилам следовать, твоя база не развалится через полгода, когда нужно будет что-то поменять. А если проигнорируешь — готовься к ночным дебагам и крикам «какого хуя тут ничего не работает!». Выбор за тобой.