Что такое внешний ключ (ForeignKey) в базах данных?

«Что такое внешний ключ (ForeignKey) в базах данных?» — вопрос из категории Базы данных, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Внешний ключ (Foreign Key, FK) — это ограничение в реляционной базе данных, которое обеспечивает ссылочную целостность данных. Он связывает поле (или набор полей) одной таблицы с первичным ключом (Primary Key, PK) другой таблицы, создавая отношение «родитель-потомок».

Основная цель: Гарантировать, что каждое значение в столбце внешнего ключа таблицы-потомка соответствует существующему значению первичного ключа в таблице-родителе. Это предотвращает появление «висячих» или «осиротевших» записей.

Пример на SQL (используя SQLite C API):

#include <sqlite3.h>
#include <iostream>

int main() {
    sqlite3* db;
    char* errMsg = 0;

    // Открываем/создаем БД
    int rc = sqlite3_open("test.db", &db);
    if (rc) { /* обработка ошибки */ }

    // Создаем таблицу-родитель (Departments)
    const char* sql_parent = R"(
        CREATE TABLE IF NOT EXISTS Departments (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL UNIQUE
        );
    )";
    rc = sqlite3_exec(db, sql_parent, 0, 0, &errMsg);

    // Создаем таблицу-потомок (Employees) с внешним ключом
    const char* sql_child = R"(
        CREATE TABLE IF NOT EXISTS Employees (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT NOT NULL,
            department_id INTEGER NOT NULL,
            FOREIGN KEY (department_id) REFERENCES Departments(id)
                ON DELETE RESTRICT   -- Запрещает удаление отдела с сотрудниками
                ON UPDATE CASCADE    -- При изменении id отдела, оно обновится и у сотрудников
        );
    )";
    rc = sqlite3_exec(db, sql_child, 0, 0, &errMsg);

    sqlite3_close(db);
    return 0;
}

Действия при нарушении ссылочной целостности (ON DELETE / ON UPDATE):

  • RESTRICT / NO ACTION: Запретить операцию, нарушающую целостность (по умолчанию во многих СУБД).
  • CASCADE: Каскадно удалить или обновить связанные записи в дочерней таблице.
  • SET NULL: Установить NULL в столбце внешнего ключа у дочерних записей (если столбец допускает NULL).
  • SET DEFAULT: Установить значение по умолчанию.

В контексте C++ и ORM: При использовании ORM-фреймворков (например, ODB, Qt SQL) внешние ключи отображаются на связи между объектами (агрегация/композиция).