Ответ
Нормальная форма Бойса-Кодда (BCNF) — это усиленная версия третьей нормальной формы (3НФ), предназначенная для устранения аномалий, связанных с функциональными зависимостями, которые не были устранены в 3НФ.
Определение:
Таблица находится в BCNF, если для каждой нетривиальной функциональной зависимости X → Y детерминант X является суперключом (т.е. содержит потенциальный ключ таблицы).
Проблема, которую решает BCNF: В 3НФ возможна ситуация, когда неключевой атрибут функционально определяет часть составного ключа, что приводит к избыточности и аномалиям обновления.
Пример нормализации в BCNF:
Исходная таблица Enrollment не в BCNF:
-- {student_id, subject} → professor, но также professor → subject
-- professor не является суперключом, нарушение BCNF.
CREATE TABLE Enrollment (
student_id INT,
subject VARCHAR(50),
professor VARCHAR(50),
PRIMARY KEY (student_id, subject)
);
Нормализация: Разделяем на две таблицы, устраняя зависимость неключевого атрибута.
-- Таблица 1: Профессор определяет предмет (professor — суперключ).
CREATE TABLE ProfessorSubject (
professor VARCHAR(50) PRIMARY KEY,
subject VARCHAR(50)
);
-- Таблица 2: Связь студента и профессора.
CREATE TABLE StudentEnrollment (
student_id INT,
professor VARCHAR(50),
PRIMARY KEY (student_id, professor),
FOREIGN KEY (professor) REFERENCES ProfessorSubject(professor)
);
Результат: Обе новые таблицы находятся в BCNF, аномалии устранены.
Ответ 18+ 🔞
Ну, вот смотри, ты сидишь, думаешь, что с базой всё чики-пуки, 3НФ вроде соблюдена, а потом — бац! — и вылезает какая-то хуйня при обновлении. И ты такой: «Ёпта, как так? Я же нормализовал!». А всё потому, что есть эта самая, блядь, Нормальная форма Бойса-Кодда (BCNF), которая, по сути, берёт 3НФ и дожимает её, как последнего мудака в тренажёрке.
Если по-простому:
Таблица в BCNF, если для каждой нетривиальной зависимости X → Y этот самый X — суперключ. То есть он должен быть таким крутым, что по нему можно однозначно всю строку идентифицировать. Если X — какая-то хилая часть ключа или вообще не ключ, то это нарушение, и тебе пизда, нужно дробить таблицу дальше.
В чём, собственно, прикол? В 3НФ могут проскочить зависимости, где неключевой атрибут определяет часть составного ключа. И вот эта хуйня порождает избыточность: ты меняешь профессора в одной записи, а у тебя в десяти других этот же предмет ведёт другой чувак, и возникает пиздец и рассогласование. BCNF эту брешь затыкает.
Разберём на живом примере, чтобы понятно было:
Допустим, есть таблица записи студентов Enrollment. Студент и предмет — ключ. Но ещё есть профессор, который этот предмет ведёт.
CREATE TABLE Enrollment (
student_id INT,
subject VARCHAR(50),
professor VARCHAR(50),
PRIMARY KEY (student_id, subject)
);
Логика такая: {student_id, subject} → professor. Вроде норм. НО! Допустим, у нас ещё и professor → subject. То есть один профессор — один предмет. И вот профессор-то суперключом не является! Он же не уникально идентифицирует запись — один профессор может учить много студентов. Нарушение BCNF налицо, ёпта!
Что происходит? Если профессор Иванов ведёт «Матан», и мы захотим поменять предмет у Иванова на «Философию», нам придётся лезть и обновлять все записи со студентами, которые к нему записаны. Ебать-колотить, какая же это залупа!
Как это лечится? Дробим, блядь, как дрова!
-
Выносим зависимость
professor → subjectв отдельную таблицу, где профессор будет уже главным по тарелке (суперключом).CREATE TABLE ProfessorSubject ( professor VARCHAR(50) PRIMARY KEY, subject VARCHAR(50) ); -
В исходной таблице оставляем только связь студента и профессора. Ключ —
(student_id, professor).CREATE TABLE StudentEnrollment ( student_id INT, professor VARCHAR(50), PRIMARY KEY (student_id, professor), FOREIGN KEY (professor) REFERENCES ProfessorSubject(professor) );
И что в сухом остатке?
Теперь всё по-взрослому. Хочешь сменить предмет у профессора — идёшь в ProfessorSubject и меняешь в одной-единственной строке. Никаких аномалий обновления, никакой избыточности. Обе таблицы теперь в BCNF, и можно спать спокойно. Ну, или почти спокойно, пока не доберёшься до 4НФ, но это уже совсем другая история, блядь.