В чём разница между первичным ключом (PRIMARY KEY) и внешним ключом (FOREIGN KEY) в реляционной БД?

Ответ

Первичный и внешний ключи — это основные механизмы обеспечения целостности данных и создания связей между таблицами в реляционных базах данных.

Характеристика Первичный ключ (PRIMARY KEY) Внешний ключ (FOREIGN KEY)
Назначение Уникально идентифицирует каждую запись (строку) в своей таблице. Устанавливает и поддерживает связь с записью в другой таблице (или иногда в той же).
Уникальность Значение должно быть уникальным в пределах таблицы. Дублирование запрещено. Значения могут повторяться. Одно значение из родительской таблицы может ссылаться на множество строк в дочерней.
Допустимость NULL Не может содержать значение NULL. Может содержать NULL, если связь не обязательна (зависит от бизнес-логики).
Количество в таблице Только один первичный ключ на таблицу (может состоять из нескольких столбцов — составной ключ). Может быть несколько внешних ключей, ссылающихся на разные таблицы.
Обеспечивает Целостность сущности (Entity Integrity). Целостность ссылок (Referential Integrity).

Практический пример в SQL:

-- Таблица-родитель (сущность "Автор")
CREATE TABLE authors (
    -- PRIMARY KEY: уникальный идентификатор автора
    author_id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL
);

-- Таблица-ребёнок (сущность "Книга")
CREATE TABLE books (
    -- PRIMARY KEY: уникальный идентификатор книги
    book_id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    -- FOREIGN KEY: ссылка на автора книги.
    -- Значение author_id ДОЛЖНО существовать в таблице authors.
    author_id INT,
    -- Определение внешнего ключа с именем (good practice)
    CONSTRAINT fk_author
        FOREIGN KEY (author_id)
        REFERENCES authors(author_id)
        ON DELETE CASCADE -- Действие при удалении автора: удалить все его книги
);

-- Вставка данных:
INSERT INTO authors (name) VALUES ('Лев Толстой'); -- author_id = 1
-- Корректная вставка: автор существует.
INSERT INTO books (title, author_id) VALUES ('Война и мир', 1);
-- Ошибка нарушения внешнего ключа: автор с id=99 не существует.
INSERT INTO books (title, author_id) VALUES ('Неизвестная книга', 99);

Проще говоря:

  • Первичный ключ — это ваш уникальный паспорт в таблице. Он доказывает, что вы — отдельная, уникальная запись.
  • Внешний ключ — это ссылка на паспорт другого человека (записи в другой таблице). Он гарантирует, что вы ссылаетесь на реально существующую запись, а не на вымышленную.

Ответ 18+ 🔞

А, ну вот, опять эти ваши ключи, блядь! Сидишь такой, думаешь — ну что за хуйня, опять про ключи? А потом бац — и понимаешь, что без них нихуя не работает, сука!

Смотри, есть два главных пацана в этой базарной истории.

Первый — это Первичный Ключ. Он как твой внутренний паспорт, блядь, в отдельно взятой таблице. Ты без него — никто, хуй с горы. Его задача — чтобы каждая строчка была уникальной сучкой, и все её знали в лицо. Два одинаковых паспорта? Не, не слышал, так не бывает. И NULL ему тоже нахуй не сдался — он всегда должен быть, конкретный и ебаный.

Второй — это Внешний Ключ. Это уже не паспорт, а, блядь, справка о родстве! Он тычет пальцем в другую таблицу и орет: «Смотрите, а вот мой батя вот в той таблице живёт, вон его паспорт номер!». Он может показывать на одного и того же папашу много раз — это нормально, детей-то дохуя. А может и показывать в пустоту (NULL) — типа, я сирота, блядь, сам по себе.

А теперь смотри, как это выглядит вживую, ебать мои старые костыли:

-- Таблица "Авторы". Тут сидят писатели, важные, блядь, персоны.
CREATE TABLE authors (
    -- Вот он, ёбаный первичный ключ! Паспорт автора. Уникальный, целый, ненулевой.
    author_id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL
);

-- Таблица "Книги". Это уже ихние дети-выкормыши.
CREATE TABLE books (
    -- Свой собственный паспорт у каждой книги тоже есть, да.
    book_id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    -- А ВОТ ОН, СУКА, ВНЕШНИЙ КЛЮЧ! Справка, кто папаша.
    -- Смотрит прямо в таблицу `authors` и тычет в столбец `author_id`.
    author_id INT,
    CONSTRAINT fk_author
        FOREIGN KEY (author_id)
        REFERENCES authors(author_id)
        ON DELETE CASCADE -- Это значит: если папашу удалили, то и все книжонки его — нахуй, в топку.
);

-- Пробуем впендюрить данные:
INSERT INTO authors (name) VALUES ('Фёдор Достоевский'); -- Паспорт №1 выдан.
-- Всё чики-пуки, папаша есть.
INSERT INTO books (title, author_id) VALUES ('Преступление и наказание', 1);
-- А ВОТ ЭТО УЖЕ ПИЗДЕЦ! Какой нахуй автор с id=666? Его нет! Нарушение целостности, ёпта!
-- База данных тебе такую хуйню не пропустит, будет орать как резаная.
INSERT INTO books (title, author_id) VALUES ('Книга из ниоткуда', 666);

Короче, вся суть в чём, блядь:

  • Первичный ключ — это ты сам. «Я — Герасим, блядь!».
  • Внешний ключ — это твоя связь с другим. «А это моя Муму, блядь!». И он гарантирует, что Муму-то реально существует, а не придумана твоим пьяным воображением. А то получится, как у того немого — кинул в озеро мешок, а там нихуя не было, одна совесть потом ебёт. Вот чтобы такого не было, эти ключи и придумали, хитрая жопа!