Основы проектирования БД: нормализация данных простыми словами, для чего нужны связи в реляционной БД, связь «один ко многим»
Нормализация данных простыми словами
Структуру базы данных необходимо проектировать таким образом, чтобы данные в ней не дублировались. Удобнее всего это делать не в СУБД, а в визуальном конструкторе схем баз данных, таком как например Database Design, чтобы вся схема бд была как на ладони.
Допустим мы проектируем структуру бд интернет-магазина. Нам нужно хранить данные о товарах, которые в нём будут продаваться. Также каждый товар принадлежит к одной из категорий товаров. Как нам хранить эти данные?
Первое что может прийти в голову - создать таблицу для товаров, хранить в каждой записи товара его название, описание, цену, и название категории: Почему так лучше не делать? Представьте ситуацию, что интернет-магазин уже действует, у него много категорий и много товаров. Потребовалось изменить название одной из категорий. При такой реализации для этого придётся вносить изменения в каждую из записей в таблице товаров, заменяя название категории на новое.
Мы храним кучу одинаковых данных, и их сложно модифицировать. К тому же может случиться и такое, что в процессе изменения названия категории в куче записей, база данных упадёт, и часть названий не будет изменена. Возникнет серьёзная несогласованность данных, что может привести к серьёзным ошибкам.
Как же следует поступить? Обратимся к главному преимуществу реляционных баз данных: возможности создавать связи между таблицами. Нам просто нужно создать для хранения данных о категориях товаров другую таблицу. Таким образом, когда нам нужно изменить название категории, изменение будет затрагивать только одну запись:
Нормализованная структура данных - концепция, в которой абсолютно одни и те же данные не могут повторяться в разных записях. То есть нам нужно хранить информацию о категориях товара - мы храним отдельно информацию о товарах, и отдельно информацию о категориях.
Как же теперь нам понять, к какой категории принадлежит товар? Нужно создать связь между товарами и категориями. Чтобы это сделать, мы добавляем в таблицу товаров поле category_id, и в каждой записи товара будем хранить там id записи категории.
id - уникальный (не повторяющийся) номер, который есть у каждой записи в любой таблице (исключение - таблицы связи многие ко многим, но об этом позже). Внутри одной таблицы не может быть два одинаковых id, что позволяет нам с 100% точностью получить нужную запись по её уникальному номеру
Смотрите, как это выглядит: Храня в записях товаров уникальный номер категории к которым они принадлежат, мы можем получая каждый товар, получать вместе с ними все данные о категории:
SELECT
p.id, p.name, p.description, p.price,
c.id as 'category_id', c.name as 'category_name', c.image as 'category_image'
FROM
product p, category c
WHERE
p.category_id = c.id;
Связь один ко многим
На скриншоте выше, мы создали связь "один ко многим", также обозначается как one-to-many или 1:М. Опять же проще объяснить на примере: в нашей связи "один" это категория, а "многие" - товары.
Это означает, что один товар может принадлежать только к одной категории (кроссовки adidas могут быть только "обувью", но не "перчатками" или "шапками"). В этот же момент, одна категория может принадлежать нескольким товарам (в "обувь" могут входить "кроссовки adidas", "кожаные сапоги", "кроссовки nike" и так далее).
Благодаря данной связи, мы обеспечиваем необходимую логику, пример которой я привёл выше. Также, мы можем получить не только информацию о категории, получая инфо о товаре, но и например получить список товаров, которые принадлежат к какой то определённой категории. Дополним наш SQL-запрос:
SELECT
p.id, p.name, p.description, p.price,
c.id as 'category_id', c.name as 'category_name', c.image as 'category_image'
FROM
product p, category c
WHERE
p.category_id = c.id
AND
c.id = N;
Где вместо N нам нужно будет подставить уникальный номер категории.
В соседних статьях вы можете найти информацию о других типах реляционных связей данных: многие ко многим, и один к одному. Если было полезно, можете поддержать лайком/комментарием/подпиской на мой образовательный YouTube-канал.