Van*_*nel 22 database-design sql-server-2012
我正在开发一个 SQL Server 2012 数据库,我有一个关于一对零或一关系的问题。
我有两张桌子,Codes
和HelperCodes
。一个代码可以有零个或一个辅助代码。这是创建这两个表及其关系的 sql 脚本:
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])
)
Run Code Online (Sandbox Code Playgroud)
那是对的吗?
Code 和 HelperCode 都是不同的实体。HelperCode 可以是已使用的(没有代码引用它),也可以是已使用的(只有一个代码引用它)。
也许 Code.HelperCodeId 必须是 Code 表主键的一部分。但我不确定空列是否可以成为主列的一部分。这样做,我想防止两个或多个代码引用相同的 HelperCode。
ype*_*eᵀᴹ 28
要回答标题中的问题,不,所有主要列都必须是NOT NULL
。
但是不改变表的设计,你可以在Code (HelperCodeId)
列上添加一个过滤索引:
CREATE UNIQUE INDEX
FUX_Code_HelperCodeId
ON dbo.Code
(HelperCodeId)
WHERE
HelperCodeId IS NOT NULL ;
Run Code Online (Sandbox Code Playgroud)
WHERE HelperCodeId IS NOT NULL
由于 SQL-Server 在唯一约束和唯一索引中处理空值的方式,需要过滤器 ( )。如果没有过滤器,SQL-Server 将不允许超过一行的NULL
in HelperCodeId
。
另一种设计是删除HelperCodeId
fromCode
并添加第三个表来存储Code
-HelperCode
关系。两个实体之间的关系似乎是零或一到零或一(一个 Code 可以没有 HelperCode,一个 HelperCode 可能不被代码使用):
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,
--
-- removed: [HelperCodeId] NVARCHAR(20) NULL,
--
CONSTRAINT [PK_Code] PRIMARY KEY CLUSTERED
(
[Id] ASC
),
CONSTRAINT [FK_Code_LevelConfiguration]
FOREIGN KEY ([Level])
REFERENCES [dbo].[LevelConfiguration] ([Level]),
) ;
Run Code Online (Sandbox Code Playgroud)
HelperCode
保持不变:
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])
) ;
Run Code Online (Sandbox Code Playgroud)
附加表将有两个UNIQUE
约束(或一个主要和一个唯一)以确保每个 Code 与(最多)一个 HelperCode 相关,而每个 HelperCode 与(最多)一个 Code 相关。两列都是NOT NULL
:
CREATE TABLE [dbo].[Code_HelperCode]
(
[CodeId] NVARCHAR(20) NOT NULL,
[HelperCodeId] NVARCHAR(20) NOT NULL,
CONSTRAINT [UQ_Code_HelperCode_CodeId]
UNIQUE (CodeId),
CONSTRAINT [UQ_Code_HelperCode_HelperCodeId]
UNIQUE (HelperCodeId),
CONSTRAINT [FK_HelperCode_Code]
FOREIGN KEY ([CodeId])
REFERENCES [dbo].[Code] ([Id]),
CONSTRAINT [FK_Code_HelperCode]
FOREIGN KEY ([HelperCodeId])
REFERENCES [dbo].[HelperCode] ([HelperCodeId])
) ;
Run Code Online (Sandbox Code Playgroud)