SQL
Как связать таблицы в MySQL
В MySQL таблицы связывают через внешний ключ FOREIGN KEY. Одна таблица хранит основную сущность, а другая хранит ссылку на нее через id
Например, есть клиенты и заказы. Один клиент может иметь много заказов, поэтому в таблице заказов хранится client_id
Пример связи один-ко-многим
Создадим таблицу клиентов:
CREATE TABLE clients (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL
) ENGINE=InnoDB;
Создадим таблицу заказов:
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
client_id INT NOT NULL,
amount DECIMAL(10, 2) NOT NULL,
FOREIGN KEY (client_id) REFERENCES clients(id)
) ENGINE=InnoDB;
Теперь MySQL не позволит добавить заказ с client_id, которого нет в таблице clients
Как добавить данные
INSERT INTO clients (name)
VALUES ('Ivan');
INSERT INTO orders (client_id, amount)
VALUES (1, 1500.00);
Если попробовать вставить заказ с несуществующим клиентом, MySQL вернет ошибку внешнего ключа:
INSERT INTO orders (client_id, amount)
VALUES (999, 1500.00);
Это нормальное поведение: база защищает связь от битых данных
Как посмотреть связанные данные
Чтобы вывести заказы вместе с клиентами:
SELECT
clients.name,
orders.id AS order_id,
orders.amount
FROM orders
JOIN clients
ON orders.client_id = clients.id;
JOIN не создает связь, а использует уже существующие поля для выборки данных
Что проверить, если связь не создается
Чаще всего проблема в одном из пунктов:
- таблицы должны использовать
InnoDB - типы связанных колонок должны совпадать
- если
idбеззнаковый,client_idтоже должен быть беззнаковым - родительская колонка должна быть индексом или первичным ключом
- в дочерней таблице не должно быть строк с несуществующими id
Проверьте структуру:
SHOW CREATE TABLE clients;
SHOW CREATE TABLE orders;
Так проще увидеть реальные типы, индексы и ограничения
Мини-практика
Создайте таблицы authors и books, где одна книга ссылается на одного автора:
CREATE TABLE authors (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL
) ENGINE=InnoDB;
CREATE TABLE books (
id INT PRIMARY KEY AUTO_INCREMENT,
author_id INT NOT NULL,
title VARCHAR(200) NOT NULL,
FOREIGN KEY (author_id) REFERENCES authors(id)
) ENGINE=InnoDB;
Затем попробуйте добавить книгу с несуществующим author_id и посмотрите ошибку
Частые ошибки
- Использовать MyISAM, где внешние ключи не работают как в InnoDB
- Делать
client_idдругого типа, чемclients.id - Добавлять связь после того, как в таблице уже есть битые ссылки
- Думать, что
JOINсам создает связь - Хранить несколько id в одной строковой колонке
- Не индексировать поля, по которым строятся связи
Что почитать дальше по SQL
Если нужен общий маршрут по теме, откройте рубрику SQL. Для соседних задач пригодятся эти разборы:
- DELETE SQL: как удалить строки из таблицы и не потерять лишние данные
- EXISTS в SQL на простых примерах
- GROUP BY и HAVING: группировка без каши
- INSERT, UPDATE, DELETE без потери данных
Как проверить результат на практике
Для SQL-материала всегда начинайте с маленькой тестовой таблицы или с ограниченного набора строк. Сначала выполните SELECT, который показывает будущие данные, затем проверьте условие WHERE, сортировку или соединение, и только после этого переходите к изменяющим командам вроде UPDATE, DELETE или ALTER TABLE. Такой порядок снижает риск случайно изменить больше строк, чем планировалось
Хорошая самопроверка простая: заранее запишите, сколько строк должно попасть в результат, какие столбцы должны измениться и что должно остаться без изменений. Если запрос возвращает неожиданный набор строк, не добавляйте новые условия вслепую, а проверьте каждую часть отдельно: фильтр, соединение, группировку и сортировку