Строго говоря, уникальный столбец с нулевым значением (или набор столбцов) может быть 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.
Для строк в объекте не были присвоены значения uniqnull (т. Е. Для тех, которые мы бы поместили в NULL в the_entity_incorrect), мы просто не добавляем строку в the_relation.
Обратите внимание, что значения для uniqnull будут уникальными для всех the_relation, а также обратите внимание, что для каждого значения в_значении в переменной может быть не более одного значения, так как первичный и внешний ключи на нем обеспечивают это.
Затем, если значение 5 для uniqnull должен быть связан с the_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
;
Оператор «left external join» гарантирует, что в результате появятся все строки from_entity, поместив NULL в столбец uniqnull, если в the_relation нет соответствующих столбцов.
Помните, что любое усилие, потраченное на несколько дней (или недель или месяцев) на разработку хорошо нормированной базы данных (и соответствующих денормализующих представлений и процедур), сэкономит вам годы (или десятилетия) боли и потраченных впустую ресурсов.
нет шансов на использование sql 2008? вы можете создать отфильтрованный индекс, используя 'where' – 2010-03-13 03:21:02
Вы не имели в виду _unique, позволяя NULLs_, вы, похоже, имели в виду _unique, но включали несколько NULLs_. В противном случае NULL индексируется как любое другое значение, а ограничение уникальности работает как ожидалось - просто не согласно стандартам SQL, как @pst, упомянутое в комментарии ниже. – Suncat2000 2012-02-09 14:28:26