如何识别保持参照完整性的父记录上的“首选”子女?

问题描述:

我正在定义一个表示由一个或多个零件项组成的页面的实体。每个页面必须至少定义一个部分。每个零件只属于一个页面。其中一个部分项目将成为页面上的“主”部分,其他所有部分将依靠主控部分。除此之外,主从部件的行为相同。如何识别保持参照完整性的父记录上的“首选”子女?

我正在看几种不同的方式来表达这在SQL中。我可以想到几个选项,每个选项都有优点和缺点。我确信没有人“正确的答案”,但我正在寻找哪些方法隐藏了复杂性的反馈意见,这些复杂性将在以后引发我的兴趣。约束和CASCADE触发器是可取的,这样其他方可以在需要时安全地修改表,但是我想避免需要复杂逻辑的设计。

在配置时,用户需要选择主控的能力,而不允许将0或多个部件标记为主控。在运行时,每个部分都需要确定它是否是主设备,或者需要依靠主设备获取信息。

我的目标平台是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 
) 

优点:简单的数据来理解;在我正在增强的基础应用程序中使用类似的方法;零件记录知道它是主机而不查找页面记录上的数据。 缺点:强制只有一个主控会要求触发器拒绝违反规则的更新或应用层代码,或两者兼而有之。

选择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值

  • 什么是模式(或者是有一个),用于插入家长和第一个强制性的孩子一个操作?
  • 删除最后一个孩子和父母的模式(或者是否存在)是什么模式,当其他部分存在时仍然会阻止删除Page和主体部分?

我怀疑我错过了一个或两个必要的细节以给出一个很好的答案。请问,我会更新。

+0

它是这样的评论,让我分心,然后再回到问题的核心>“我会在执行时倾向于使用GUID键”。现在我想抛开你的问题并谈论这个评论。为什么你会用整套的GUID? [不断增加的集群密钥 - 集群索引辩论.........。重要! - 金伯利特里普](http://www.sqlskills.com/blogs/kimberly/ever-increasing-clustering-key-the-clustered-index-debate-again/) – SqlZim

+0

我想我用那个评论淹没了水。这并没有真正的相关性,但是在我向前迈进之前,我一定会阅读你的链接。谢谢! – Bruce

+0

我阅读了您的文章,并欣赏关于页面拆分的评论(真的,因为我也是)。在我的情况下,最大的表格将只包含数百行,如果我乐观的话可能会包含数千行。将键值分配给另一个数据库(维护交叉引用)的密钥值比拥有统一增加的密钥更重要。设置数据,而不是交易数据。不过,谢谢你的回击。这就是我来这里的原因。 – Bruce

我将与选项1一起使用。您对选项1的缺点不正确:可以使用调用UDF的CHECK CONSTRAINT强制执行“唯一且唯一的一个主”规则。这就是我会用的。

+0

如果他们想让不同的部分成为主人呢?有没有一个很好的方式来执行这个原子?也许在新的部件上设置标志将清除它在旧的主控制器上,或者我应该写一个更新...设置IsMasterPart =(1 - IsMasterPart)PartKey in(@old,@new)? – Bruce

+0

它可以通过一个精心构造的更新来自动完成(我认为):SET SETMasterPart = CASE when somecondtion THEN 1 ELSE 0 END ...' –