Будет ли работать Foreign Key одной таблицы относящийся к Unique Key другой таблицы, если Unique Key состоит из 2 колонок и одна из них имеет значение NULL?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Foreign Key с Unique Key, содержащим NULL
Это отличный вопрос о тонкостях реляционных баз данных. Ответ: Да, Foreign Key будет работать, но с важными оговорками.
Поведение с NULL в UNIQUE KEY
В SQL существует особенность: NULL считается уникальным значением. То есть, если у вас есть UNIQUE KEY (col1, col2) и col1 или col2 содержит NULL, это не нарушает ограничение уникальности.
-- Таблица с UNIQUE KEY из двух колонок
CREATE TABLE Parent (
id INT PRIMARY KEY,
code VARCHAR(50),
region VARCHAR(50),
UNIQUE KEY uk_code_region (code, region)
);
-- Эти строки все допустимы (NULL != NULL)
INSERT INTO Parent VALUES (1, A, US);
INSERT INTO Parent VALUES (2, A, NULL); -- OK
INSERT INTO Parent VALUES (3, NULL, US); -- OK
INSERT INTO Parent VALUES (4, NULL, NULL); -- OK
Foreign Key, ссылающийся на UNIQUE KEY с NULL
Да, Foreign Key может ссылаться на Unique Key (не обязательно на Primary Key). Но при наличии NULL возникают интересные сценарии:
-- Таблица-дочка со Foreign Key
CREATE TABLE Child (
id INT PRIMARY KEY,
parent_code VARCHAR(50),
parent_region VARCHAR(50),
FOREIGN KEY fk_parent (parent_code, parent_region)
REFERENCES Parent(code, region)
);
-- Какие строки можно вставить в Child?
INSERT INTO Child VALUES (1, A, US); -- OK (ссылается на parent id=1)
INSERT INTO Child VALUES (2, A, NULL); -- ??
INSERT INTO Child VALUES (3, NULL, US); -- ??
INSERT INTO Child VALUES (4, NULL, NULL); -- ??
Правило NULL в Foreign Key
В SQL стандарте и большинстве СУБД (PostgreSQL, MySQL, Oracle):
Eсли ANY колонка в Foreign Key содержит NULL, то ограничение Foreign Key НЕ проверяется. Это связано с тем, что NULL означает "неизвестное значение", и базе данных непонятно, как проверить ограничение.
// Из кода Java это выглядит так:
if (parentCode != null && parentRegion != null) {
// Проверяем Foreign Key
validateForeignKeyExists(parentCode, parentRegion);
} else {
// NULL пропускается (как правило)
}
Практический пример (PostgreSQL)
-- Гарантированно работает
INSERT INTO Child VALUES (1, A, US); -- ✓ Проверка FK пройдёт
-- NULL пропускают проверку FK
INSERT INTO Child VALUES (2, A, NULL); -- ✓ Вставится (NULL не проверяется)
INSERT INTO Child VALUES (3, NULL, NULL); -- ✓ Вставится
-- Несуществующий родитель
INSERT INTO Child VALUES (4, X, Y); -- ✗ Ошибка (FK нарушено)
Итоговый ответ
Foreign Key будет работать, но:
- Если обе колонки заполнены — проверяется наличие соответствующей строки в Parent
- Если хотя бы одна колонка NULL — проверка Foreign Key пропускается
- NULL не нарушает уникальность UNIQUE KEY, поэтому можно иметь несколько строк с NULL
Это нужно учитывать при проектировании базы данных. Если вам нужна строгая ссылочная целостность, избегайте NULL в Foreign Key колонках.