Короткий ответ
Первичный ключ (PRIMARY KEY) однозначно идентифицирует строку таблицы и не допускает NULL/дублей, а внешний ключ (FOREIGN KEY) ссылается на первичный (или уникальный) ключ другой таблицы и обеспечивает ссылочную целостность между ними.
Как это работает подробнее
PK создаёт уникальный индекс и ограничение NOT NULL+UNIQUE на одну или несколько колонок; FK добавляет ограничение, что значение колонки должно существовать среди значений PK/UNIQUE родительской таблицы, иначе вставка/обновление отклоняется.
Пример кода
example.sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
author_id INTEGER NOT NULL REFERENCES authors(id) ON DELETE CASCADE
);
-- Удаление автора автоматически удалит все его книги
-- (проверяется: DELETE FROM authors WHERE id = 1; затем SELECT * FROM books;)Что использовать на практике
- Практика. PK выбирают либо естественный (например, email, если он реально уникален и стабилен), либо суррогатный (SERIAL/UUID); FK настраивают с ON DELETE/ON UPDATE (CASCADE, RESTRICT, SET NULL) в зависимости от бизнес-логики удаления связанных записей.
Подводные камни
- Ошибка. Забывают добавить ON DELETE поведение и получают ошибку при удалении родителя; используют естественный ключ, который со временем меняется (например, email после смены пользователем), что требует болезненной миграции FK.