Ответ
В реляционных СУБД существует три основных типа связей (отношений), реализуемых через внешние ключи (FOREIGN KEY):
-
Один к одному (One-to-One, 1:1)
- Одна запись в таблице А связана не более чем с одной записью в таблице В, и наоборот.
- Зачем: Для разделения редко используемых или конфиденциальных данных (например, основные данные пользователя и его паспортные данные).
CREATE TABLE users (id SERIAL PRIMARY KEY, email VARCHAR UNIQUE); CREATE TABLE user_profiles ( user_id INT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE, passport_data TEXT );
-
Один ко многим (One-to-Many, 1:N)
- Наиболее распространенный тип. Одна запись в таблице А может быть связана со многими записями в таблице В, но запись в В ссылается только на одну запись в А.
- Пример: Один автор (таблица
authors) может написать много книг (таблицаbooks).CREATE TABLE authors (id SERIAL PRIMARY KEY, name TEXT); CREATE TABLE books ( id SERIAL PRIMARY KEY, title TEXT, author_id INT REFERENCES authors(id) -- Внешний ключ в таблице "многих" );
-
Многие ко многим (Many-to-Many, M:N)
- Одна запись в А может быть связана со многими записями в В, и наоборот. Реализуется через промежуточную таблицу-связку (junction table).
- Пример: Студенты и курсы. Один студент посещает много курсов, на одном курсе учится много студентов.
CREATE TABLE students (id SERIAL PRIMARY KEY, name TEXT); CREATE TABLE courses (id SERIAL PRIMARY KEY, title TEXT); -- Промежуточная таблица CREATE TABLE student_courses ( student_id INT REFERENCES students(id), course_id INT REFERENCES courses(id), PRIMARY KEY (student_id, course_id) -- Составной первичный ключ );
Ответ 18+ 🔞
А, вот это, блядь, классика! Реляционные базы, связи, внешние ключи... Ну, сука, как в жизни, только без сантиментов, чистая логика, блядь. Слушай, разжую, как есть, чтобы понятно было даже тому, кто SQL от SOL путает.
1. Один к одному (1:1) Ну, это как брак в идеальном мире, которого не существует, ёпта. Одна сущность в таблице А — и ей соответствует ровно одна, блядь, сущность в таблице Б, и наоборот. Зачем это нахуй? Ну, например, чтобы от греха подальше. Основные данные пользователя в одной таблице, а его паспортные данные, кредитная история и размер члена — в другой, защищённой, блядь, таблице. Чисто технически, чтобы не тащить всё в одну кучу.
CREATE TABLE users (id SERIAL PRIMARY KEY, email VARCHAR UNIQUE);
CREATE TABLE user_profiles (
user_id INT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
passport_data TEXT
);
Смотри, user_id тут не просто внешний ключ, а ещё и первичный, блядь! Это и есть гарантия, что на одного юзера — один профиль, и всё, пиздец. ON DELETE CASCADE — это чтобы, если юзера удалили, его профиль автоматом в пизду полетел, не мусорил.
2. Один ко многим (1:N) А вот это, сука, хлеб наш насущный, самый частый сценарий! Один чувак может натворить дохуя всего. Один автор — много книг. Один отдел — много сотрудников. Один пост в бложике — много комментов от ебанатов. Запись в таблице «один» может плодить сколько угодно записей в таблице «многие». А вот каждая запись из «многих» смотрит преданно только на своего одного.
CREATE TABLE authors (id SERIAL PRIMARY KEY, name TEXT);
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT,
author_id INT REFERENCES authors(id) -- Внешний ключ в таблице "многих"
);
Вот он, красавец, author_id в таблице books. Это и есть та самая верёвочка, которая тянется к папочке-автору. Без него книга — сирота, блядь, беспризорник.
3. Многие ко многим (M:N)
О, а это уже вечеринка, ёбана! Полный бардак и свобода отношений. Один студент ходит на много курсов. Один курс слушает много студентов. Как это смоделировать, а? Если просто впихнуть student_id в таблицу courses — получится пиздец, один курс будет только у одного студента. И наоборот.
Вот тут-то и появляется она, блядь, таблица-связка, или junction table, или, как я её называю, «сводница ебаная». Она разводит всех и со всеми.
CREATE TABLE students (id SERIAL PRIMARY KEY, name TEXT);
CREATE TABLE courses (id SERIAL PRIMARY KEY, title TEXT);
-- А вот и наша сводня
CREATE TABLE student_courses (
student_id INT REFERENCES students(id),
course_id INT REFERENCES courses(id),
PRIMARY KEY (student_id, course_id) -- Составной первичный ключ, ёпта!
);
Гениальность в простоте, блядь! Эта таблица-связка — просто список пар «студент-курс». Составной первичный ключ (student_id, course_id) не даёт записать одну и ту же пару дважды, чтобы студент не записался на один курс пять раз, как мудак. А ссылки есть и на студентов, и на курсы. Всё, схема готова, можно запускать оргию связей.
Вот и вся магия, блядь. Ничего сложного, если не перемудрить. Главное — понять, какая связь в твоей голове, а потом уже переносить её в базу, а не наоборот.