如何在保持参照完整性的父记录上识别 "preferred" 子项?
How to identify a "preferred" child on a parent record maintaining referential integrity?
我正在定义一个实体,它代表一个由一个或多个部分项目组成的页面。每个 Page 必须至少定义一个 Part。每个 Part 只属于一个 Page。部分项目之一将是页面上的 "master" 部分,所有其他部分将依赖于主。除了这个差异,主从部分的行为完全相同。
我正在研究在 SQL 中表达这一点的几种不同方式。我可以想到几个选项,每个选项都有优点和缺点。我确定没有人 "right answer,",但我正在寻找有关哪些方法具有隐藏的复杂性的反馈,这些复杂性稍后会咬我的屁股。约束和 CASCADE 触发器是可取的,这样其他方可以在需要时安全地修改表,但我想避免需要曲折、复杂逻辑的设计。
在配置时,用户需要能够选择主节点,而不允许将 0 个或多个部分标记为主节点。在运行时,每个部分都需要识别自己是master,还是需要依赖master获取信息。
我的目标平台是 Microsoft SQL Server 2008 或更高版本。下面的示例使用 int 键只是因为它使示例更小——我倾向于在实现时使用 GUID 键。
选项 1 - 主零件上的标志
create table [Page] (
PageKey int identity primary key,
PageName varchar(30) not NULL
)
go
create table [Part] (
PartKey int identity primary key,
PartName varchar(30) not NULL,
PageKey int not null,
constraint fkPage foreign key (PageKey) references [Page](PageKey),
IsMasterPart bit not NULL default 0
)
优点:数据简单易懂;我正在增强的基础应用程序中使用的类似方法; Part 记录知道它是 master,而无需在 Page 记录上查找数据。
缺点:强制使用一个且唯一的master,需要触发器拒绝违反规则和/或应用层代码的更新。
选项 2 - 页面上的外键
create table [Page] (
PageKey int identity primary key,
PageName varchar(30) not NULL,
MasterPartKey int not NULL
)
go
create table [Part] (
PartKey int identity primary key,
PartName varchar(30) not NULL,
PageKey int not null,
constraint fkPage foreign key (PageKey) references [Page](PageKey),
IsMasterPart bit not NULL default 0
)
go
alter table [Page]
add constraint fkMasterPart
foreign key (MasterPartKey) references [Part](PartKey)
优点:DRI防止删除主零件;只能有一个主零件;不能有没有主部件的页面
缺点:分配 PK/FK 值
时可能存在先有鸡还是先有蛋的问题
- 在一个操作中插入父项和第一个强制子项的模式是什么(或是否存在)?
- 删除最后一个子项和父项的模式是什么(或是否存在),当其他部分存在时仍然会阻止删除页面和主部分?
我怀疑我错过了一两个提供良好答案所必需的细节。请提问,我会更新。
我会选择选项 1。选项 1 的缺点是不正确的:"one and only one master" 规则可以通过调用 UDF 的 CHECK CONSTRAINT 来强制执行。这就是我要使用的。
我正在定义一个实体,它代表一个由一个或多个部分项目组成的页面。每个 Page 必须至少定义一个 Part。每个 Part 只属于一个 Page。部分项目之一将是页面上的 "master" 部分,所有其他部分将依赖于主。除了这个差异,主从部分的行为完全相同。
我正在研究在 SQL 中表达这一点的几种不同方式。我可以想到几个选项,每个选项都有优点和缺点。我确定没有人 "right answer,",但我正在寻找有关哪些方法具有隐藏的复杂性的反馈,这些复杂性稍后会咬我的屁股。约束和 CASCADE 触发器是可取的,这样其他方可以在需要时安全地修改表,但我想避免需要曲折、复杂逻辑的设计。
在配置时,用户需要能够选择主节点,而不允许将 0 个或多个部分标记为主节点。在运行时,每个部分都需要识别自己是master,还是需要依赖master获取信息。
我的目标平台是 Microsoft SQL Server 2008 或更高版本。下面的示例使用 int 键只是因为它使示例更小——我倾向于在实现时使用 GUID 键。
选项 1 - 主零件上的标志
create table [Page] (
PageKey int identity primary key,
PageName varchar(30) not NULL
)
go
create table [Part] (
PartKey int identity primary key,
PartName varchar(30) not NULL,
PageKey int not null,
constraint fkPage foreign key (PageKey) references [Page](PageKey),
IsMasterPart bit not NULL default 0
)
优点:数据简单易懂;我正在增强的基础应用程序中使用的类似方法; Part 记录知道它是 master,而无需在 Page 记录上查找数据。 缺点:强制使用一个且唯一的master,需要触发器拒绝违反规则和/或应用层代码的更新。
选项 2 - 页面上的外键
create table [Page] (
PageKey int identity primary key,
PageName varchar(30) not NULL,
MasterPartKey int not NULL
)
go
create table [Part] (
PartKey int identity primary key,
PartName varchar(30) not NULL,
PageKey int not null,
constraint fkPage foreign key (PageKey) references [Page](PageKey),
IsMasterPart bit not NULL default 0
)
go
alter table [Page]
add constraint fkMasterPart
foreign key (MasterPartKey) references [Part](PartKey)
优点:DRI防止删除主零件;只能有一个主零件;不能有没有主部件的页面 缺点:分配 PK/FK 值
时可能存在先有鸡还是先有蛋的问题- 在一个操作中插入父项和第一个强制子项的模式是什么(或是否存在)?
- 删除最后一个子项和父项的模式是什么(或是否存在),当其他部分存在时仍然会阻止删除页面和主部分?
我怀疑我错过了一两个提供良好答案所必需的细节。请提问,我会更新。
我会选择选项 1。选项 1 的缺点是不正确的:"one and only one master" 规则可以通过调用 UDF 的 CHECK CONSTRAINT 来强制执行。这就是我要使用的。