Je développe une base de données SQL Server 2012 et j'ai une question sur une relation un à zéro ou un.
J'ai deux tables, Codes
et HelperCodes
. Un code peut avoir zéro ou un code d'assistance. Voici le script sql pour créer ces deux tables et leurs relations:
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])
)
Est-ce exact?
Un code et un HelperCode sont deux entités différentes. Un HelperCode peut être utilisé (aucun code ne le référence) ou utilisé (un seul code le référence).
Peut-être que Code.HelperCodeId doit faire partie de la clé primaire de la table Code. Mais je ne sais pas si une colonne nulle pourrait faire partie d'un primaire. Ce faisant, je veux empêcher que deux ou plusieurs codes référencent le même HelperCode.
database-design
sql-server-2012
VansFannel
la source
la source
HelperCodeId
faire partie du PK? Est-ce, par hasard, parce que vous voulez empêcher deux codes ou plus de référencer le même HelperCode?HelperCodeId
colonne comme Unique.Réponses:
Pour répondre à la question dans le titre, non, toutes les colonnes principales doivent l'être
NOT NULL
.Mais sans modifier la conception des tables, vous pouvez ajouter un index filtré sur la
Code (HelperCodeId)
colonne:Le filtre (
WHERE HelperCodeId IS NOT NULL
) est nécessaire en raison de la façon dont SQL-Server traite les valeurs nulles dans les contraintes uniques et les index uniques. Sans le filtre, SQL-Server n'autoriserait pas plus d'une ligne avecNULL
inHelperCodeId
.Une autre conception consisterait à supprimer le
HelperCodeId
deCode
et à ajouter une troisième table qui stockera les relationsCode
-HelperCode
. La relation entre les deux entités semble être Zero-or-One - to - Zero-or-One (un code ne peut pas avoir de HelperCode et un HelperCode peut être utilisé par aucun code):HelperCode
reste inchangé:La table supplémentaire aura deux
UNIQUE
contraintes (ou une principale et une unique) pour garantir que chaque code est lié à (maximum) un HelperCode et que chaque HelperCode est lié à (maximum) un code. Les deux colonnes seraientNOT NULL
:la source
Essayez plutôt d'utiliser une contrainte unique. Soi-disant la norme ANSI a déclaré null comme une clé primaire non valide, mais je n'ai jamais vu la norme et je ne souhaite pas l'acheter pour le vérifier.
Ne pas avoir de clés nulles semble être l'une de ces choses que les développeurs ont une croyance très dure dans un sens ou dans l'autre. Ma préférence est de les utiliser, car je trouve cela utile pour les tables de recherche contenant des info-bulles et des données associées pour les zones de liste déroulante qui ne sont pas remplies.
On m'a appris que la valeur Null indique qu'une variable n'a jamais été définie et que la valeur vide indique que la valeur a été définie dans le passé. Bien sûr, c'est au développeur de définir pour l'application, mais je trouve absurde d'autoriser les clés primaires vides mais pas les clés primaires nulles.
la source