Какие типы связей между таблицами существуют в реляционных базах данных?

Ответ

В реляционных СУБД существует три основных типа связей (отношений), реализуемых через внешние ключи (FOREIGN KEY):

  1. Один к одному (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
      );
  2. Один ко многим (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) -- Внешний ключ в таблице "многих"
      );
  3. Многие ко многим (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) не даёт записать одну и ту же пару дважды, чтобы студент не записался на один курс пять раз, как мудак. А ссылки есть и на студентов, и на курсы. Всё, схема готова, можно запускать оргию связей.

Вот и вся магия, блядь. Ничего сложного, если не перемудрить. Главное — понять, какая связь в твоей голове, а потом уже переносить её в базу, а не наоборот.