Когда вы впервые сталкиваетесь с базами данных, всё кажется немного запутанным: таблицы, строки, какие-то «ключи»… Но если объяснить это на живых примерах — всё становится куда яснее. Давайте разберёмся, что такое первичный ключ, внешний ключ, и ещё одно важное пон — суррогатный ключ.
Таблица как ящик с карточками
Представьте себе таблицу в базе данных как ящик, полный карточек с информацией. Например, у нас есть таблица пользователей users
:
1 2 3 4 5 |
CREATE TABLE users ( id INT PRIMARY KEY, -- суррогатный и первичный ключ name VARCHAR(100), email VARCHAR(100) ); |
Пример данных в таблице users:
id | имя | |
---|---|---|
1 | Катя | katya@shra.ru |
2 | Олег | oleg@shra.ru |
3 | Маша | masha@shra.ru |
Что вообще значит «ключ»?
«Ключ» — это способ однозначно найти нужную строку. В таблице users
можно было бы использовать email
как ключ — ведь он обычно уникален. Но на практике используют именно id
, потому что:
email
может измениться;id
короче, проще и быстрее обрабатывается, т.к. обычно это число;- с ним меньше шансов на ошибки — к примеру разночтение символов в написании, если использовать
email
.
Вот тут и появляется понятие:
Суррогатный ключ — это искусственный (технический) идентификатор, который не имеет смысла сам по себе, но обеспечивает уникальность. Обычно это просто автоинкрементное поле
id
.
1 2 3 4 5 |
CREATE TABLE users ( id SERIAL PRIMARY KEY, -- суррогатный ключ name TEXT, email TEXT ); |
Наверное, вы заметили, что второй пример содержит ключевое слово SERIAL вместо INT. Это не связано с суррогатностью ключа, это просто удобный ярлык (синтаксический сахар), который говорит базе — сделай мне поле INT, но с автоинкрементом для новых значений.
Вторая таблица — заказы. Знакомьтесь: внешний ключ
Допустим, у нас есть таблица orders
, где хранятся заказы:
1 2 3 4 5 |
CREATE TABLE orders ( id SERIAL PRIMARY KEY, user_id INT REFERENCES users(id), -- внешний ключ item TEXT ); |
Пример данных:
id | user_id | Товар |
---|---|---|
1 | 2 | Книга |
2 | 2 | Флешка |
3 | 1 | Наушники |
Как таблицы «связываются»
- В
users.id
— первичный ключ (ещё и суррогатный). - В
orders.user_id
— внешний ключ, который указывает наusers.id
.
Это позволяет:
- не дублировать имя пользователя в каждом заказе;
- легко получать данные о заказах и владельцах.
Для запроса данных из разных таблиц используется ключевое слово JOIN:
1 2 3 |
SELECT orders.item, users.name FROM orders JOIN users ON orders.user_id = users.id; |
Результат запроса:
item | name |
---|---|
Книга | Олег |
Флешка | Олег |
Наушники | Катя |
Что делает внешний ключ?
Он говорит базе данных: «Эта колонка должна ссылаться на записи в другой таблице.» И если вы попытаетесь вставить user_id = 999
, а такого пользователя нет — произойдёт ошибка:
1 2 |
INSERT INTO orders (user_id, item) VALUES (999, 'Планшет'); -- ERROR: insert or update on table "orders" violates foreign key constraint |
Что будет если удалить пользователя?
Поведение базы зависит от настройки внешнего ключа. Можно настроить так, чтобы:
- база данных не позволяла удалить пользователя, пока у него есть заказы;
- или автоматически удаляла связанные заказы (
ON DELETE CASCADE
); - или просто обнуляла поле (
ON DELETE SET NULL
).
Пример:
1 2 3 4 5 |
CREATE TABLE orders ( id SERIAL PRIMARY KEY, user_id INT REFERENCES users(id) ON DELETE CASCADE, item TEXT ); |
Теперь при удалении пользователя удалятся и его заказы:
1 2 |
DELETE FROM users WHERE id = 2; -- Все заказы Олега тоже будут удалены |
Итак:
- Первичный ключ — уникальный идентификатор строки. (Как паспорт)
- Суррогатный ключ — это искусственный первичный ключ, вроде
id
. Он не зависит от внешних данных. - Внешний ключ — это ссылка из одной таблицы на другую. Как «указатель» — кто с кем связан. Он не содержит данные сам по себе, но указывает на них.