Основы проектирования БД: как создать связь «многие ко многим» (М:М) и когда нужен этот тип связи, простыми словами на примере
Когда нам нужна связь «многие ко многим» (М:М)?
Когда мы хотим получить возможность привязать любую запись из таблицы А к нескольким записям таблицы Б, и в то же время - привязать любую запись из таблицы Б к нескольким записям таблицы А.
Рассмотрим реальный пример такой ситуации на примере проектирования базы данных интернет-магазина: у нас есть пользователи и товары. Пользователь перед покупкой складывает товары в виртуальную корзину. Что это значит с точки зрения архитектуры? Один пользователь может добавить себе в корзину несколько разных товаров. Один ко многим? Не спешите с выводами: ведь один и тот же товар, может быть добавлен в корзину совершенно разными пользователями!
И как же нам наиболее рационально хранить данные какие товары у каких пользователей добавлены в корзину? На помощь приходит связь «многие ко многим»!
Как создать связь «многие ко многим» (М:М)?
Нам потребуется создать дополнительную таблицу, и в ней мы будем указывать связи. Для этого в таблице достаточно двух столбцов: в первом будем хранить уникальный идентификатор (id) записи таблицы А (в нашем случае - пользователя), а во втором будем хранить id таблицы Б (в нашем случае - товара). Назовём таблицу по смыслу - cart (корзина)
В большинстве случаев таблицы связей М:М принято называть так: названиеТаблицыА_названиеТаблицыБ. Но если вы видите, что назвать по смыслу будет понятнее - рекомендую называть по смыслу.
Вот так выглядит связь «многие ко многим»:
Как работать со связью «многие ко многим» (М:М)?
Разберём на нашем же примере. Пользователь добавляет товар в корзину:
INSERT into cart (user, product) VALUES ( user.id, product.id );
Так добавляют разные пользователи разные товары. А теперь мы можем ловко получить содержимое корзины конкретного пользователя:
SELECT
p.id,
p.name,
p.price
FROM
product p,
cart c
WHERE
c.product = p.id
AND
c.user = ?;
Где знак вопроса - подставляем уникальный идентификатор (id) пользователя, и получаем в выдаче все подробности о товарах, находящихся в корзине только у этого пользователя.
Если пользователь удаляет товар из корзины, нам достаточно удалить запись из таблицы cart, в которой совпадает id товара и id пользователя. Всё очень просто:
DELETE FROM cart WHERE user = user.id AND product = product.id;
Главная сила реляционных баз данных в том, что мы можем вместо всей информации о том же самом товаре в корзине у пользователя, хранить только уникальный номер записи товара. И благодаря этому уникальному номеру, мы можем вытащить всю всю информацию об этом товаре, и это касается любой записи в базе данных.
В том числе мы можем вытащить информацию и у других связей той записи, которую мы саму получаем благодаря связи. Таким образом мы исключаем дублирование данных, другими словами нормализуем данные.
В соседних статьях вы можете найти информацию о других типах реляционных связей данных: один ко многим, и один к одному, а также более подробно о нормализации. Обязательно ознакомьтесь с этой информацией, если находитесь в начале пути проектирования архитектуры баз данных.
Если было полезно, можете поддержать лайком/комментарием/подпиской на мой образовательный YouTube-канал.