Примеры SQL-кода создания всех типов связей в MySQL
При работе с базами данных часто приходится использовать несколько таблиц для хранения данных. Более или менее крупный проект требует логической связи между таблицами, для того чтоб упростить и ускорить поиск нужной информации. Для этого есть такая вещ как связи таблиц mysql, создаётся связь с помощью внешних ключей (FOREIGN KEY). Ниже представлены примеры создания таблиц и организации связей one-to-one, one-to-many и many-to-many с использованием FOREIGN KEY в MySQL.
Связь один к одному (One-to-One)
Связь один к одному используется когда для строки записи в одной таблице используется одна строка записи в другой таблице. Например, у пользователя есть только один определенный ранг/роль из 5 возможных.
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE user_profiles (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL UNIQUE,
full_name VARCHAR(255),
bio TEXT,
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
Данный sql код дает нам такую логику связи:
- user_profiles.user_id имеет UNIQUE, поэтому одному пользователю соответствует только один профиль.
- ON DELETE CASCADE автоматически удаляет профиль при удалении пользователя.
Связь один ко многим (One-to-Many)
Такая связь один ко многим применяется когда одна запись в таблице связана с несколькими записями из другой таблицы. Например, категория имеет множество статей или товаров.
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL
);
CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,
category_id INT NOT NULL,
title VARCHAR(255),
content TEXT,
FOREIGN KEY (category_id) REFERENCES categories(id)
ON DELETE SET NULL
ON UPDATE CASCADE
);
Такая связь mysql таблиц дает нам следующее:
- Одна категория может иметь множество статей.
- При удалении категории поле category_id станет NULL.
Связь многие ко многим (Many-to-Many)
Для такой связи многие ко многим нужна третья таблица как промежуточная. Именно она будет держать в себе связь двух других таблиц. Например, есть множество товаров и есть множество тегов, как тег может содержать в себе много товаров так и товар может содержать много тегов.
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE tags (
id INT AUTO_INCREMENT PRIMARY KEY,
tag_name VARCHAR(100) NOT NULL
);
CREATE TABLE product_tags (
product_id INT NOT NULL,
tag_id INT NOT NULL,
PRIMARY KEY (product_id, tag_id),
FOREIGN KEY (product_id) REFERENCES products(id)
ON DELETE CASCADE
ON UPDATE CASCADE,
FOREIGN KEY (tag_id) REFERENCES tags(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
Происходит после создания таких таблиц следующее:
- Любой товар может иметь множество тегов.
- Любой тег может относиться к множеству товаров.
- PRIMARY KEY (product_id, tag_id) запрещает дублирование связей.
Связь — самосвязь (Self-Reference/Рекурсивная связь)
Данный подход используется в одной таблице, обычно используется для древовидного выведения информации, например, комментариев или категорий с подкатегориями, меню разного уровня и т.д.
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
parent_id INT DEFAULT NULL,
FOREIGN KEY (parent_id) REFERENCES categories(id)
ON DELETE SET NULL
ON UPDATE CASCADE
);
Достаточно в одной записи указать просто идентификатор родительской записи, если она есть.
- parent_id указывает на id в той же таблице.
- Категория может иметь подкатегории.
Связь с таблицей-справочником (Lookup table)
Используется для ограниченного набора значений, например, для установки статуса заказа, наличия товара на складе и т.п.
CREATE TABLE order_statuses (
id INT AUTO_INCREMENT PRIMARY KEY,
status_name VARCHAR(50) NOT NULL
);
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
status_id INT NOT NULL,
amount DECIMAL(10,2),
FOREIGN KEY (status_id) REFERENCES order_statuses(id)
ON DELETE RESTRICT
ON UPDATE CASCADE
);
Статус не может быть удалён, если он используется (RESTRICT).
Наглядная таблица связей MySQL
Базовое понимание логики связей между таблицами mysql даст вам большой опыт профессиональной разработки проектов, где все будет работать быстрее и понятнее. А также, советуем обратить внимание на типы данных связываемых ячеек, про типы данных мы рассказывали в прошлом материале: типы данных в mysql. Приводим в пример таблицу:
| Тип связи | Описание | Как реализуется в MySQL | Пример | Когда используется |
|---|---|---|---|---|
| One-to-One (1:1) | Каждой записи в первой таблице соответствует не более одной записи во второй таблице. | PRIMARY KEY + UNIQUE FOREIGN KEY |
Таблица users и таблица user_profiles. Каждый пользователь имеет один профиль. |
Хранение дополнительных данных, вынесенных из основной таблицы (оптимизация, безопасность). |
| One-to-Many (1:N) | Одна запись таблицы A может иметь много связанных записей таблицы B. | FOREIGN KEY в дочерней таблице, указывающий на PRIMARY KEY родительской. |
Таблица categories и products. Одна категория — много товаров. |
Наиболее распространённый тип связи: пользователи → заказы, категории → товары, автор → статьи. |
| Many-to-Many (M:N) | Каждая запись таблицы A может быть связана с несколькими записями таблицы B и наоборот. | Создаётся промежуточная таблица (join table) с двумя FOREIGN KEY. |
Таблицы students и courses. Промежуточная student_course связывает многие-ко-многим. |
Теги у постов, студенты на курсах, роли у пользователей. |
| Self-referencing (Связь с самой собой) | Записи таблицы могут ссылаться на другие записи той же таблицы. | FOREIGN KEY, указывающий на тот же PRIMARY KEY таблицы. | Таблица employees, где employee.manager_id ссылается на employees.id. | Древовидные структуры: сотрудники → начальники, категории → подкатегории. |
| Optional Relationship (Необязательная связь) | Связанная запись может отсутствовать (NULL допускается). | FOREIGN KEY допускает NULL. | Таблица posts может иметь author_id, но запись может быть анонимной (NULL). | Для полей, где связь не обязательна. |
| Mandatory Relationship (Обязательная связь) | Связанная запись должна существовать (NULL запрещён). | FOREIGN KEY + NOT NULL. | Таблица orders обязательно содержит user_id покупателя. | Когда без связи объект не может существовать. |
| Cascade Delete | При удалении записи удаляются все связанные записи. | FOREIGN KEY … ON DELETE CASCADE | При удалении категории удаляются её товары. | Каскадное удаление зависимых данных. |
| Cascade Update | При обновлении первичного ключа обновляется внешний ключ. | FOREIGN KEY … ON UPDATE CASCADE | Изменение id родителя автоматически обновляет значения в дочерней таблице. | Для таблиц, где id может изменяться (редко используется). |
| Restrict / No Action | Запрещает удаление или обновление записи, если есть связанные данные. | FOREIGN KEY … ON DELETE RESTRICT / NO ACTION | Нельзя удалить пользователя, если у него есть заказы. | Для защиты критичных данных. |
| Set NULL | При удалении связанной записи внешний ключ устанавливается в NULL. | FOREIGN KEY … ON DELETE SET NULL | При удалении автора — статья остаётся, author_id становится NULL. | Когда зависимый объект должен остаться без связи. |