В SQL, будет ли работать внешний ключ (FOREIGN KEY) на составной уникальный ключ (UNIQUE KEY), если одна из колонок в уникальном ключе содержит NULL?

«В SQL, будет ли работать внешний ключ (FOREIGN KEY) на составной уникальный ключ (UNIQUE KEY), если одна из колонок в уникальном ключе содержит NULL?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ответ зависит от СУБД. В большинстве систем, включая MySQL, это работает, но с важным ограничением.

Поведение в MySQL/InnoDB:

  • Составной UNIQUE KEY допускает дублирование строк, если хотя бы один столбец в ключе содержит NULL.
  • FOREIGN KEY может ссылаться на такую строку, но целостность данных может быть нарушена, так как в родительской таблице может быть несколько "неуникальных" строк с NULL.

Пример в MySQL:

CREATE TABLE Parent (
    col1 INT,
    col2 INT,
    UNIQUE KEY uk_parent (col1, col2) -- Составной уникальный ключ
);

CREATE TABLE Child (
    id INT PRIMARY KEY,
    fk_col1 INT,
    fk_col2 INT,
    FOREIGN KEY (fk_col1, fk_col2)
        REFERENCES Parent(col1, col2)
);

-- Вставка в Parent (допустима, т.к. col2 = NULL)
INSERT INTO Parent VALUES (1, NULL);
INSERT INTO Parent VALUES (1, NULL); -- Повторная вставка разрешена!

-- Вставка в Child (будет работать)
INSERT INTO Child VALUES (100, 1, NULL);

Почему это проблема: Внешний ключ теперь ссылается на одну из нескольких возможных строк в Parent, что нарушает принцип однозначной ссылки. В PostgreSQL поведение строже: UNIQUE ограничение считает все NULL значения разными, поэтому дублирования не возникнет.