厳密に言えば、一意の null 許容列 (または列のセット) が NULL (または NULL のレコード) になるのは 1 回だけです。これは、同じ値 (およびこれには NULL を含む) が 2 回以上存在すると明らかに一意制約に違反するためです。
ただし、それは「一意の null 許容列」の概念が有効であることを意味するものではありません。リレーショナルデータベースに実際に実装するには、この種のデータベースは適切に機能するように正規化する必要があることを覚えておく必要があります.正規化には通常、エンティティ間の関係を確立するためにいくつかの(エンティティではない)余分なテーブルを追加する必要があります. .
「一意のnull許容列」を1つだけ考慮して基本的な例を考えてみましょう。それをより多くの列に拡張するのは簡単です。
次のようなテーブルで表される情報があるとします。
create table the_entity_incorrect
(
id integer,
uniqnull integer null, /* we want this to be "unique and nullable" */
primary key (id)
);
uniqnull を分離し、2 つ目のテーブルを追加して、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 の行に一意の null 値が関連付けられていない場合 (つまり、the_entity_incorrect に NULL を入れる行の場合)、単に the_relation に行を追加しません。
uniqnull の値はすべての the_relation で一意であることに注意してください。また、the_entity の各値に対して、the_relation の値は最大で 1 つになることに注意してください。これは、主キーと外部キーがこれを強制するためです。
次に、uniqnull の値 5 を the_entity id 3 に関連付ける場合は、次のことを行う必要があります。
start transaction;
insert into the_entity (id) values (3);
insert into the_relation (the_entity_id, uniqnull) values (3, 5);
commit;
そして、the_entity の id 値 10 に対応する一意の null がない場合は、次のことのみを行います。
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 からのすべての行が結果に表示されることを保証し、一致する列が the_relation に存在しない場合、uniqnull 列に NULL を置きます。
適切に正規化されたデータベース (および対応する非正規化ビューと手順) を設計するために数日 (または数週間または数か月) を費やすことで、何年 (または何十年) もの労力と無駄なリソースを節約できます。