Строго кажучи, унікальний нульовий стовпець (або набір стовпців) може бути NULL (або записом NULL) лише один раз, оскільки мати одне і те ж значення (а це включає NULL) більше одного разу очевидно порушує унікальне обмеження.
Однак це не означає, що концепція "унікальних нульових стовпців" є дійсною; щоб реально реалізувати його у будь-якій реляційній базі даних, ми просто маємо мати на увазі, що цей тип баз даних має бути нормалізований для належної роботи, а нормалізація зазвичай передбачає додавання декількох (не-сутнісних) додаткових таблиць для встановлення взаємозв'язків між сутностями .
Давайте попрацюємо з базовим прикладом, розглядаючи лише один "унікальний нульовий стовпчик", його легко розгорнути на більше таких стовпців.
Припустимо, ми подаємо інформацію, представлену такою таблицею:
create table the_entity_incorrect
(
id integer,
uniqnull integer null, /* we want this to be "unique and nullable" */
primary key (id)
);
Ми можемо це зробити, розставивши uniqnull і додавши другу таблицю, щоб встановити зв'язок між значеннями uniqnull та the_entity (а не мати uniqnull "всередині the_entity"):
create table the_entity
(
id integer,
primary key(id)
);
create table the_relation
(
the_entity_id integer not null,
uniqnull integer not null,
unique(the_entity_id),
unique(uniqnull),
/* primary key can be both or either of the_entity_id or uniqnull */
primary key (the_entity_id, uniqnull),
foreign key (the_entity_id) references the_entity(id)
);
Щоб пов’язати значення uniqnull з рядком у the_entity, нам також потрібно додати рядок у the_relation.
Для рядків у the_entity не було пов'язано жодних значень uniqnull (тобто для тих, у яких ми би поставили NULL в the_entity_incorrect), ми просто не додаємо рядок у the_relation.
Зауважте, що значення uniqnull будуть унікальними для всіх відносин__, а також зауважте, що для кожного значення в the_entity може бути не більше одного значення у the_relation, оскільки первинні та зовнішні ключі на ньому примусово застосовують це.
Тоді, якщо значення 5 для uniqnull має бути пов’язане з ідентифікатором__entity 3, нам потрібно:
start transaction;
insert into the_entity (id) values (3);
insert into the_relation (the_entity_id, uniqnull) values (3, 5);
commit;
І якщо значення id 10 для the_entity не має аналога uniqnull, ми робимо лише:
start transaction;
insert into the_entity (id) values (10);
commit;
Щоб денормалізувати цю інформацію та отримати дані, якими міститься таблиця на зразок the_entity_incorrect, нам потрібно:
select
id, uniqnull
from
the_entity left outer join the_relation
on
the_entity.id = the_relation.the_entity_id
;
Оператор "лівого зовнішнього з'єднання" гарантує, що всі рядки з the_entity з'являться в результаті, ставлячи NULL у стовпчик uniqnull, коли у the_relation немає відповідних стовпців.
Пам’ятайте, будь-які зусилля, витрачені протягом декількох днів (або тижнів чи місяців) на розробку добре нормалізованої бази даних (і відповідних денормалізуючих поглядів та процедур), заощадять вам роки (або десятиліття) болю та марних ресурсів.