Frage

Ich bin mit SQL Server 2005. Ich mag die Werte in einer Spalte beschränken, einzigartig zu sein, während NULLS ermöglicht.

Meine aktuelle Lösung beinhaltet einen eindeutigen Index für eine Sicht wie folgt:

CREATE VIEW vw_unq WITH SCHEMABINDING AS
    SELECT Column1
      FROM MyTable
     WHERE Column1 IS NOT NULL

CREATE UNIQUE CLUSTERED INDEX unq_idx ON vw_unq (Column1)

Jede bessere Ideen?

War es hilfreich?

Lösung

Ziemlich sicher, dass Sie das nicht tun, da sie den Zweck der unique verletzt.

Allerdings scheint diese Person eine menschenwürdige Arbeit zu haben, um: http://sqlservercodebook.blogspot.com /2008/04/multiple-null-values-in-unique-index-in.html

Andere Tipps

SQL Server Mit 2008 können Sie einen gefilterten Index erstellen: http: / /msdn.microsoft.com/en-us/library/cc280372.aspx . (Ich sehe Simon dies als Kommentar hinzugefügt, aber dachte, es seine eigene Antwort verdient, wie der Kommentar leicht übersehen wird.)

Eine weitere Option ist ein Auslöser Eindeutigkeit zu überprüfen, aber diese Leistung beeinträchtigen könnte.

Der berechnete Spalte Trick wird als „nullbuster“ weithin bekannt; meine Notizen Kredit Steve Kass:

CREATE TABLE dupNulls (
pk int identity(1,1) primary key,
X  int NULL,
nullbuster as (case when X is null then pk else 0 end),
CONSTRAINT dupNulls_uqX UNIQUE (X,nullbuster)
)

Genau genommen eine einzigartige Nullable-Spalte (oder Gruppe von Spalten) kann NULL sein (oder eine Aufzeichnung von NULL-Werten) nur einmal, da mit dem gleichen Wert (und dazu gehört auch NULL) mehr als einmal offensichtlich verletzt die eindeutige Einschränkung.

Doch das bedeutet nicht, das Konzept der „einzigartiger Nullable-Spalten“ gültig ist; tatsächlich es in jeder relationalen Datenbank implementieren wir im Auge behalten müssen nur, dass diese Art von Datenbanken richtig normalisiert werden sollen arbeiten, und die Normalisierung in der Regel beinhaltet die Zugabe von mehreren (nicht-Einheit) zusätzliche Tabellen Beziehungen zwischen den Einheiten zu etablieren .

Lassen Sie uns ein einfaches Beispiel arbeiten auf eine „eindeutige Nullable-Säule“ unter Berücksichtigung, es ist einfach, es zu mehr solche Spalten zu erweitern.

Angenommen, wir die Informationen durch eine Tabelle wie folgt 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 es tun, indem uniqnull auseinander setzen und das Hinzufügen eine zweite Tabelle, die eine Beziehung zwischen uniqnull Werten und the_entity (anstatt uniqnull „innen“ the_entity) herzustellen:

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 einen Wert von uniqnull einer Zeile in the_entity assoziieren wir müssen auch eine Zeile in the_relation hinzuzufügen.

Für Zeilen in the_entity waren keine uniqnull Werte zugeordnet sind (das heißt für die, die wir NULL in the_entity_incorrect setzen würde) wir einfach nicht eine Zeile in the_relation hinzuzufügen.

Beachten Sie, dass für uniqnull Werte werden für alle the_relation eindeutig sein, und auch feststellen, dass es für jeden Wert in the_entity höchstens einen Wert in the_relation sein kann, da die Primär- und Fremdschlüssel auf sie 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 uniqnull Gegenstück hat, wir nur tun:

start transaction;
insert into the_entity (id) values (10); 
commit;

Um diese Informationen denormalize und erhalten die Daten eine Tabelle wie the_entity_incorrect halten 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
;

Die „linke äußere Verknüpfung“ Operator sorgt dafür, alle Zeilen aus the_entity im Ergebnis erscheint, NULL in der uniqnull Spalte setzen, wenn keine passenden Spalten vorhanden sind, in the_relation.

Denken Sie daran, verbrachte jede Anstrengung für einige Tage (oder Wochen oder Monate) eine gut normalisierte Datenbank (und die entsprechenden Denormalisierung Ansichten und Verfahren) bei der Gestaltung wird Ihnen jahrelang sparen (oder Jahrzehnte) von Schmerz und verschwendet Ressourcen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top