Database design 更新复合主键

Database design 更新复合主键,database-design,Database Design,关于是否在我的SQL Server数据库上使用复合主键,我正在进行哲学上的讨论。我过去一直使用代理键,我正在挑战自己,离开我的舒适区去尝试一些不同的东西。我读了很多讨论,但还没有找到任何解决办法。当我不得不用复合PK更新一个记录时,我所面临的困难 例如,问题中的记录如下: ContactID, RoleID, EffectiveDate, TerminationDT 这种情况下的主键是(ContactID、RoleID、EffectiveDate)终止DT可以为空 如果在我的UI中,用户更改R

关于是否在我的SQL Server数据库上使用复合主键,我正在进行哲学上的讨论。我过去一直使用代理键,我正在挑战自己,离开我的舒适区去尝试一些不同的东西。我读了很多讨论,但还没有找到任何解决办法。当我不得不用复合PK更新一个记录时,我所面临的困难

例如,问题中的记录如下:

ContactID, RoleID, EffectiveDate, TerminationDT
这种情况下的主键是
(ContactID、RoleID、EffectiveDate)
<代码>终止DT可以为空

如果在我的UI中,用户更改
RoleID
,然后我需要更新记录。使用代理键,我可以执行
更新表集合RoleID=1,其中代理ID=Z
。但是,使用复合键方式,一旦复合键中的一个字段发生更改,我就无法引用旧记录来更新它,而现在必须在UI的某个地方维护对旧值的引用


我不在UI中绑定数据源。我打开一个连接,获取数据并将其存储在一个存储桶中,然后关闭连接。大家的意见是什么?谢谢。

通过引用“旧记录”之类的概念,您的意思是,这种关系具有独立于复合关键元素的语义。您需要一个键来引用旧记录这一事实意味着复合键元素是不够的。当然,您仍然维护外键,但我很清楚,这里需要一个主键,而不是通常意义上的代理键


在我看来,使用代理密钥是没有内疚感的。

你走在正确的轨道上,但看看你的主键,我建议你仔细看看。我认为您应该尽量避免使用复合键,并尝试在每个表中使用一个主键,除非有必要。您可以以RoleID为例,将其设置为自己的表,其中包含角色描述以及其他定义角色的内容,并将其作为外键引用放在其他表中。

首先是简单部分:

看起来你的桌子是一个对照表,不是吗?在本例中,我发现复合键工作得非常好,如果,这是一个很大的如果,如果您的UI和其他库理解它们。现在很多UI都没有,听起来你的UI也没有。因此:

1) 使用复合键进行交叉引用是正确的,这是少数几个始终有意义的地方之一,但是:

2) 如果代理键可以简化其余的编码,那么您也可以在其中添加代理键,但请记住在这三列上添加一个唯一的约束

更进一步说,您可能需要一个检查约束,以确保日期范围中没有重叠,因为数据库本身不支持“范围主键”,这看起来就像您正在做的一样


说到这里,让我把事情弄得更混乱。为什么要更新此行?正确的操作不是在原始联系人上添加终止日期,并强制创建一个新行,指示联系人的新角色吗?在这种情况下,您可能需要保留组合并稍微修改UI,以允许/禁止某些操作。

我想我应该进一步澄清一下。ContactID和RoleID是外键。ContactID和RoleID分别是Contact和Role表中的主键。从用户的角度考虑(GASP!!),假设用户在原始条目上犯了错误,并且因为角色不正确而不得不返回并更改角色?在完美世界中,旧角色将过期,新角色将在任期日期后开始。我可以强制用户删除不正确的记录,并输入一个新的正确记录,我已经考虑在UI中这样做。日期的验证(没有重叠)发生在UI中。嘿,当想到用户时,不要喘息,只要我能让我的程序员这样做:)我想你必须决定如果用户必须删除/插入,这有多重要。任何用户都会很快发现他们无法更改它,并且会删除它。这真的取决于您对用户基础的了解程度。@VBCSharp:“验证发生在UI中”每当我在DB数据完整性的上下文中听到这一点,我都会非常怀疑?我宁愿在调用DB之前验证用户输入,并让DB抛出错误,从而避免重复日期。这就是说,如果有什么东西通过了UIs验证过程,DB上有一些限制也可以防止日期重叠。@VBCSharp:那对我来说没问题。我经常在UI中复制约束,以避免DB异常太多+1。IMO主键必须是不可变的-一旦分配给它,它就永远不会更改。时期如果它改变了,那不是PK,这是我在本例中反对使用复合PK的想法。谢谢你的解释!!