我正在开发一个 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])
)
那是对的吗?
Code 和 HelperCode 都是不同的实体。HelperCode 可以是已使用的(没有代码引用它),也可以是已使用的(只有一个代码引用它)。
也许 Code.HelperCodeId 必须是 Code 表主键的一部分。但我不确定空列是否可以成为主列的一部分。这样做,我想防止两个或多个代码引用相同的 HelperCode。
要回答标题中的问题,不,所有主要列都必须是
NOT NULL
.但在不改变表设计的情况下,您可以在
Code (HelperCodeId)
列上添加过滤索引:WHERE HelperCodeId IS NOT NULL
由于 SQL-Server 在唯一约束和唯一索引中处理空值的方式,需要过滤器 ( )。如果没有过滤器,SQL-Server 将不允许超过一行NULL
inHelperCodeId
。另一种设计是删除
HelperCodeId
fromCode
并添加第三个表来存储Code
-HelperCode
关系。两个实体之间的关系似乎是零或一到零或一(代码都可以没有 HelperCode 并且 HelperCode 可能没有代码使用):HelperCode
保持不变:附加表将具有两个
UNIQUE
约束(或一个主要约束和一个唯一约束),以确保每个代码都与(最大)一个 HelperCode 相关,并且每个 HelperCode 与(最大)一个代码相关。两列都是NOT NULL
:请尝试使用唯一约束。据说 ANSI 标准将空值作为主键声明为无效,但我从未见过该标准,也不想购买它来验证这一点。
没有空键似乎是开发人员以一种或另一种方式非常难以相信的事情之一。我的偏好是使用它们,因为我发现它对于包含工具提示和未填充组合框的相关数据的查找表很有帮助。
我被告知 Null 值表示从未设置过变量,而空值表示过去已设置过该值。当然,这取决于开发人员为应用程序定义,但我发现允许空主键但不允许空主键是荒谬的。