Что такое foreign key в PostgreSQL?

JuniorPostgreSQL · Backend·Обновлено 30 июля 2026
Коротко
Foreign key (внешний ключ) — это ограничение, которое обеспечивает ссылочную целостность между двумя таблицами, гарантируя что значение в столбце дочерней таблицы обязательно существует в столбце родительской таблицы.

Что такое Foreign Key

Foreign Key (внешний ключ) — это ограничение целостности (CONSTRAINT), которое создаёт связь между двумя таблицами. Столбец или группа столбцов в дочерней таблице должны содержать только те значения, которые уже существуют в указанном столбце родительской (referenced) таблицы.

Простыми словами: если у вас есть таблица orders со столбцом user_id, foreign key гарантирует, что в user_id нельзя записать идентификатор несуществующего пользователя.

Синтаксис объявления

При создании таблицы

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INTEGER NOT NULL,
    amount NUMERIC(10, 2),
    -- объявляем внешний ключ
    CONSTRAINT fk_orders_user
        FOREIGN KEY (user_id)
        REFERENCES users(id)
);

Добавление к существующей таблице

ALTER TABLE orders
    ADD CONSTRAINT fk_orders_user
    FOREIGN KEY (user_id)
    REFERENCES users(id);

Поведение при удалении и обновлении (ON DELETE / ON UPDATE)

Когда запись в родительской таблице удаляется или обновляется, PostgreSQL может вести себя по-разному — это настраивается через ON DELETE и ON UPDATE:

Действие Поведение
NO ACTION Ошибка, если есть зависимые строки (по умолчанию)
RESTRICT Аналогично NO ACTION, но проверка немедленная
CASCADE Удалить / обновить зависимые строки автоматически
SET NULL Установить NULL в зависимом столбце
SET DEFAULT Установить значение по умолчанию
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INTEGER,
    CONSTRAINT fk_orders_user
        FOREIGN KEY (user_id)
        REFERENCES users(id)
        ON DELETE SET NULL   -- при удалении пользователя обнуляем user_id
        ON UPDATE CASCADE    -- при смене id пользователя обновляем user_id
);

Составной внешний ключ

Foreign key может ссылаться на несколько столбцов одновременно:

CREATE TABLE order_items (
    order_id INTEGER,
    product_id INTEGER,
    quantity INTEGER,
    -- составной внешний ключ
    CONSTRAINT fk_order_items
        FOREIGN KEY (order_id, product_id)
        REFERENCES order_products(order_id, product_id)
);

Важные нюансы

  • Столбец, на который ссылается foreign key, должен иметь ограничение PRIMARY KEY или UNIQUE.
  • По умолчанию PostgreSQL создаёт индекс на первичном ключе, но не создаёт автоматически индекс на столбце внешнего ключа в дочерней таблице — его нужно добавлять вручную для ускорения JOIN-запросов и каскадных операций.
  • Foreign key можно временно отключить командой SET session_replication_role = replica; (используется при массовой загрузке данных).

Что хочет услышать интервьюер

Понимание, что foreign key обеспечивает ссылочную целостность между таблицами

Знание синтаксиса: FOREIGN KEY ... REFERENCES ...

Понимание опций ON DELETE / ON UPDATE (особенно CASCADE и SET NULL)

Осознание, что referenced-столбец должен быть PRIMARY KEY или UNIQUE

Знание о том, что индекс на FK-столбце не создаётся автоматически и его нужно добавлять вручную

Пример: Базовый пример: таблицы users и orders

-- Родительская таблица
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

-- Дочерняя таблица с внешним ключом
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INTEGER NOT NULL,
    amount NUMERIC(10, 2),
    CONSTRAINT fk_orders_user
        FOREIGN KEY (user_id)
        REFERENCES users(id)
        ON DELETE CASCADE
);

-- Добавляем индекс на FK-столбец вручную
CREATE INDEX idx_orders_user_id ON orders(user_id);

-- Вставка корректной записи
INSERT INTO users (name) VALUES ('Иван');
INSERT INTO orders (user_id, amount) VALUES (1, 1500.00);

-- Попытка вставить запись с несуществующим user_id — ошибка
INSERT INTO orders (user_id, amount) VALUES (999, 500.00);
-- ERROR: insert or update on table "orders" violates foreign key constraint

Типичные ошибки

Путают направление связи: думают, что FK можно ставить на любой столбец, а не только ссылающийся на PK/UNIQUE

Не знают разницу между ON DELETE RESTRICT и ON DELETE NO ACTION (RESTRICT проверяет немедленно, NO ACTION — в конце транзакции)

Забывают создавать индекс на столбце внешнего ключа, что приводит к медленным JOIN и каскадным удалениям

Считают, что CASCADE удаляет только один уровень вложенности, а не рекурсивно все зависимые записи

Не понимают, что NULL-значение в FK-столбце допустимо и не нарушает ограничение (NULL не ссылается ни на что)

Лучшие курсы по теме

изображение курса

Docker и Ansible

Антон Ларичев
AI-тренажерыAI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Node.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Nest.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее