Genau genommen kann eine eindeutige nullfähige Spalte (oder ein Satz von Spalten) nur einmal NULL (oder ein Datensatz von NULL) sein, da der gleiche Wert (und dies schließt NULL ein) mehr als einmal offensichtlich gegen die eindeutige Einschränkung verstößt.
Dies bedeutet jedoch nicht, dass das Konzept der "eindeutigen nullbaren Spalten" gültig ist. Um es tatsächlich in einer relationalen Datenbank zu implementieren, müssen wir nur berücksichtigen, dass diese Art von Datenbanken normalisiert werden soll, um ordnungsgemäß zu funktionieren. Bei der Normalisierung werden normalerweise mehrere (Nicht-Entitäts-) zusätzliche Tabellen hinzugefügt, um Beziehungen zwischen den Entitäten herzustellen .
Lassen Sie uns ein einfaches Beispiel für nur eine "eindeutige nullfähige Spalte" erstellen. Es ist einfach, sie auf weitere solche Spalten zu erweitern.
Angenommen, wir haben die Informationen, die durch eine Tabelle wie diese dargestellt werden:
create table the_entity_incorrect
(
id integer,
uniqnull integer null, /* we want this to be "unique and nullable" */
primary key (id)
);
Wir können dies tun, indem wir uniqnull auseinander setzen und eine zweite Tabelle hinzufügen, um eine Beziehung zwischen uniqnull-Werten und the_entity herzustellen (anstatt uniqnull "innerhalb" der_entity zu haben):
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)
);
Um einer Zeile in the_entity den Wert uniqnull zuzuordnen, müssen wir auch eine Zeile in the_relation hinzufügen.
Für Zeilen in the_entity, in denen keine eindeutigen Werte zugeordnet sind (dh für diejenigen, die NULL in the_entity_incorrect setzen würden), fügen wir einfach keine Zeile in the_relation hinzu.
Beachten Sie, dass die Werte für uniqnull für die gesamte Beziehung eindeutig sind, und beachten Sie auch, dass es für jeden Wert in der Entität höchstens einen Wert in der Beziehung geben kann, da der Primär- und der Fremdschlüssel dies erzwingen.
Wenn dann ein Wert von 5 für uniqnull mit einer the_entity-ID von 3 verknüpft werden soll, müssen wir:
start transaction;
insert into the_entity (id) values (3);
insert into the_relation (the_entity_id, uniqnull) values (3, 5);
commit;
Und wenn ein ID-Wert von 10 für the_entity kein eindeutiges Gegenstück hat, tun wir nur:
start transaction;
insert into the_entity (id) values (10);
commit;
Um diese Informationen zu denormalisieren und die Daten zu erhalten, die eine Tabelle wie the_entity_incorrect enthalten würde, müssen wir:
select
id, uniqnull
from
the_entity left outer join the_relation
on
the_entity.id = the_relation.the_entity_id
;
Der Operator "linker äußerer Join" stellt sicher, dass alle Zeilen aus der Entität im Ergebnis angezeigt werden, und setzt NULL in die eindeutige Spalte, wenn in der Beziehung keine übereinstimmenden Spalten vorhanden sind.
Denken Sie daran, dass jeder Aufwand, der für einige Tage (oder Wochen oder Monate) beim Entwerfen einer gut normalisierten Datenbank (und der entsprechenden denormalisierenden Ansichten und Verfahren) aufgewendet wird, Ihnen Jahre (oder Jahrzehnte) an Schmerz und verschwendeten Ressourcen erspart.