Ich entwickle eine SQL Server 2012-Datenbank und habe eine Frage zu einer Eins-zu-Null-Oder-Eins-Beziehung.
Ich habe zwei Tische Codes
und HelperCodes
. Ein Code kann null oder einen Hilfscode haben. Dies ist das SQL-Skript zum Erstellen dieser beiden Tabellen und ihrer Beziehungen:
CREATE TABLE [dbo].[Code]
(
[Id] NVARCHAR(20) NOT NULL,
[Level] TINYINT NOT NULL,
[CommissioningFlag] TINYINT NOT NULL,
[SentToRanger] BIT NOT NULL DEFAULT 0,
[LastChange] NVARCHAR(50) NOT NULL,
[UserName] NVARCHAR(50) NOT NULL,
[Source] NVARCHAR(50) NOT NULL,
[Reason] NVARCHAR(200) NULL,
[HelperCodeId] NVARCHAR(20) NULL,
CONSTRAINT [PK_Code] PRIMARY KEY CLUSTERED
(
[Id] ASC
),
CONSTRAINT [FK_Code_LevelConfiguration]
FOREIGN KEY ([Level])
REFERENCES [dbo].[LevelConfiguration] ([Level]),
CONSTRAINT [FK_Code_HelperCode]
FOREIGN KEY ([HelperCodeId])
REFERENCES [dbo].[HelperCode] ([HelperCodeId])
)
CREATE TABLE [dbo].[HelperCode]
(
[HelperCodeId] NVARCHAR(20) NOT NULL,
[Level] TINYINT NOT NULL,
[CommissioningFlag] TINYINT NOT NULL,
[LastChange] NVARCHAR(50) NOT NULL,
CONSTRAINT [PK_HelperCode] PRIMARY KEY CLUSTERED
(
[HelperCodeId] ASC
),
CONSTRAINT [FK_HelperCode_LevelConfiguration]
FOREIGN KEY ([Level])
REFERENCES [dbo].[LevelConfiguration] ([Level])
)
Ist das korrekt?
Ein Code und ein HelperCode sind unterschiedliche Entitäten. Ein HelperCode kann ein verwendeter (kein Code verweist darauf) oder ein verwendeter (nur ein Code verweist darauf) sein.
Möglicherweise muss Code.HelperCodeId Teil des Primärschlüssels der Codetabelle sein. Ich bin mir aber nicht sicher, ob eine Nullspalte Teil einer Primärspalte sein könnte. Auf diese Weise möchte ich verhindern, dass zwei oder mehr Codes auf denselben HelperCode verweisen.
quelle
HelperCodeId
ein Teil der PK sein wollen? Liegt es vielleicht daran, dass Sie verhindern möchten, dass zwei oder mehr Codes auf denselben HelperCode verweisen?HelperCodeId
Spalte als eindeutig festzulegen.Antworten:
Um die Frage im Titel zu beantworten, müssen alle Primärspalten nein sein
NOT NULL
.Ohne das Design der Tabellen zu ändern, können Sie der
Code (HelperCodeId)
Spalte einen gefilterten Index hinzufügen :Der filter (
WHERE HelperCodeId IS NOT NULL
) wird benötigt, weil SQL-Server Nullen in eindeutigen Einschränkungen und eindeutigen Indizes behandelt. Ohne den Filter würde SQL-Server nicht mehr als eine Zeile mitNULL
in zulassenHelperCodeId
.Ein alternatives Design wäre das Entfernen
HelperCodeId
vonCode
und Hinzufügen einer dritten Tabelle, in der dieCode
-HelperCode
Beziehungen gespeichert werden . Die Beziehung zwischen den beiden Entitäten scheint Null oder Eins zu Null oder Eins zu sein (beide, ein Code kann keinen HelperCode haben und ein HelperCode kann von keinem Code verwendet werden):HelperCode
bleibt unverändert:Die zusätzliche Tabelle enthält zwei
UNIQUE
Bedingungen (oder eine primäre und eine eindeutige), um sicherzustellen, dass jeder Code (maximal) einem HelperCode und jeder HelperCode (maximal) einem Code zugeordnet ist. Beide Spalten wärenNOT NULL
:quelle
Verwenden Sie stattdessen eine eindeutige Einschränkung. Angeblich hat der ANSI-Standard Nullen als ungültigen Primärschlüssel deklariert, aber ich habe den Standard noch nie gesehen und möchte ihn nicht kaufen, um dies zu überprüfen.
Das Fehlen von Null-Schlüsseln scheint eines der Dinge zu sein, an die Entwickler auf die eine oder andere Weise nur sehr schwer glauben. Ich bevorzuge es, sie zu verwenden, da ich sie für Nachschlagetabellen mit QuickInfos und zugehörigen Daten für Kombinationsfelder hilfreich finde, die nicht ausgefüllt wurden.
Mir wurde beigebracht, dass ein Nullwert angibt, dass noch nie eine Variable festgelegt wurde, und ein leerer Wert angibt, dass der Wert in der Vergangenheit festgelegt wurde. Natürlich muss der Entwickler dies für die Anwendung definieren, aber ich finde es unsinnig, leere Primärschlüssel, aber keine Null-Primärschlüssel zuzulassen.
quelle