Estou desenvolvendo um banco de dados do SQL Server 2012 e tenho uma pergunta sobre um relacionamento um para zero ou um.
Eu tenho duas mesas Codes
e HelperCodes
. Um código pode ter zero ou um código auxiliar. Este é o script sql para criar essas duas tabelas e seus relacionamentos:
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])
)
Isso está correto?
Um código e um HelperCode são entidades diferentes. Um HelperCode pode ser usado (nenhum código faz referência a ele) ou usado (apenas um código faz referência a ele).
Talvez Code.HelperCodeId deva fazer parte da chave primária da tabela Código. Mas não tenho certeza se uma coluna nula pode fazer parte de uma primária. Fazendo isso, quero impedir que dois ou mais códigos façam referência ao mesmo HelperCode.
database-design
sql-server-2012
VansFannel
fonte
fonte
HelperCodeId
de fazer parte do PK? É por acaso que você deseja impedir que dois ou mais códigos façam referência ao mesmo HelperCode?HelperCodeId
coluna como Exclusiva.Respostas:
Para responder à pergunta no título, não, todas as colunas principais precisam estar
NOT NULL
.Mas sem alterar o design das tabelas, você pode adicionar um índice filtrado na
Code (HelperCodeId)
coluna:O filter (
WHERE HelperCodeId IS NOT NULL
) é necessário devido à maneira como o SQL-Server trata nulos em restrições e índices exclusivos. Sem o filtro, o SQL-Server não permitiria mais de uma linha comNULL
inHelperCodeId
.Um projeto alternativo seria remover a
HelperCodeId
partir deCode
e adicionar uma terceira tabela que armazenará osCode
-HelperCode
relacionamentos. O relacionamento entre as duas entidades parece ser Zero-ou-Um-para-Zero-ou-Um (tanto um Código não pode ter HelperCode quanto um HelperCode pode ser usado por nenhum Código):HelperCode
continua sem alteração:A tabela adicional terá duas
UNIQUE
restrições (ou uma primária e uma única) para garantir que todo Código esteja relacionado a (no máximo) um HelperCode e cada HelperCode esteja relacionado a (no máximo) um Código. Ambas as colunas seriamNOT NULL
:fonte
Tente usar uma restrição exclusiva. Supostamente, o padrão ANSI declarou nulos como chave primária como inválido, mas nunca vi o padrão e não desejo comprá-lo para verificar isso.
Não ter chaves nulas parece ser uma daquelas coisas que os desenvolvedores acreditam muito de uma maneira ou de outra. Minha preferência é usá-los porque acho útil para tabelas de pesquisa que contêm dicas de ferramentas e dados relacionados para caixas de combinação que não foram preenchidas.
Fui ensinado que o valor nulo indica que uma variável nunca foi definida e o valor vazio indica que o valor foi definido no passado. É claro que depende do desenvolvedor definir para o aplicativo, mas acho absurdo permitir chaves primárias vazias, mas não chaves primárias nulas.
fonte