如何以最自然的方式在Sql Server中对零或一到零或一的关系建模?
有一个“危险”表,列出了站点上的危险。有一个“任务”表,用于需要在站点上完成的工作。有些任务是修复危险,没有任务可以应对多种危险。有些危害有修复它们的任务。没有任何危险可以使两个任务相关联。
以下是我能想到的最好的方法:
CREATE TABLE [dbo].[Hazard](
[HazardId] [int] IDENTITY(1,1) NOT NULL,
[TaskId] [int] NULL,
[Details] [varchar](max) NULL,
CONSTRAINT [PK_Hazard] PRIMARY KEY CLUSTERED
(
[HazardId] ASC
))
GO
ALTER TABLE [dbo].[Hazard] WITH CHECK ADD CONSTRAINT [FK_Hazard_Task] FOREIGN KEY([TaskId])
REFERENCES [dbo].[Task] ([TaskId])
GO
CREATE TABLE [dbo].[Task](
[TaskId] [int] IDENTITY(1,1) NOT NULL,
[HazardId] [int] NULL,
[Details] [varchar](max) NULL,
CONSTRAINT [PK_Task] PRIMARY KEY CLUSTERED
(
[TaskId] ASC
))
GO
ALTER TABLE [dbo].[Task] WITH CHECK ADD CONSTRAINT [FK_Task_Hazard] FOREIGN KEY([HazardId])
REFERENCES [dbo].[Hazard] ([HazardId])
GO
你会做不同的吗?我对此设置不满意的原因是,需要使用应用程序逻辑来确保任务和危害指向彼此,而不是其他任务和危害,并且没有任务/危害指向相同的危害/任务另一个任务/危险指向。
有没有更好的办法?
有什么原因不能在危险表上的TaskID上创建唯一索引,而在任务表上不能创建HazardID唯一索引?这样一来,您就只能在表中包含其中之一,这是我认为您想要实现的目标。
—
mskinner
@mskinner,但它们不是唯一的,很多都可以
—
Andrew Savinykh
null
。
啊,知道了 在那种情况下,Ben-Gan先生在sqlmag.com/sql-server-2008/unique-constraint-multiple-nulls上写了大量关于如何创建约束以允许多个null的 文章。我认为这对您有用。让我知道是否。
—
mskinner
附带说明一下,使用过滤索引存在许多问题,因此如果您不熟悉,则可能值得一读。这是一个很好的博客。 blogs.msdn.com/b/sqlprogrammability/archive/2009/06/29/… ,但是对于这种特定情况,假设其他问题不会给您带来太多麻烦,它可能对您来说效果很好。
—
mskinner
FWIW唯一的经过过滤的索引只能将唯一性应用于非空行,例如
—
Aaron Bertrand
CREATE UNIQUE INDEX x ON dbo.Hazards(TaskID) WHERE TaskID IS NOT NULL;