据我了解,第三范式(3NF)基本上意味着应该只有一把钥匙。
如果一个带有自动递增id
列的表也有一个已知唯一且不为空的列,例如社会保险号,则该其他列可以用作键。
忽略实际/业务问题(例如,将 SSN 作为密钥/FK 传递时的安全/隐私风险),从严格的模式设计方面来看,这样的表是否不在 3NF 中,因为实际上有 2 个密钥?
答案是否会根据另一列是否有唯一键而有所不同?如果是这样,为什么?
据我了解,第三范式(3NF)基本上意味着应该只有一把钥匙。
如果一个带有自动递增id
列的表也有一个已知唯一且不为空的列,例如社会保险号,则该其他列可以用作键。
忽略实际/业务问题(例如,将 SSN 作为密钥/FK 传递时的安全/隐私风险),从严格的模式设计方面来看,这样的表是否不在 3NF 中,因为实际上有 2 个密钥?
答案是否会根据另一列是否有唯一键而有所不同?如果是这样,为什么?
EFCodd,1971,数据库关系模型的进一步规范化
在关系的定义中隐含了一个关系必须至少有一个键。3NF 或任何其他范式都没有要求一个关系应该只有一个键。
不幸的是,关于数据库设计和规范化的书籍有大量仅具有单个键的关系示例,而具有多个键的示例则更少。这让我觉得很奇怪,因为现在多个键似乎是非常普遍的做法。非学术文献中缺乏实际例子似乎是导致人们混淆键在数据库设计中的作用的原因之一。造成混淆的另一个原因是流行的助记符“nothing but the key”。该短语通常归因于 Bill Kent,但它并不是 3NF 的准确定义。
No. 2NF、3NF 和 Boyce Codd Normal Form (BCNF) 处理函数依赖。2NF 中的表意味着不存在部分键依赖关系,其中非键列依赖于多列键的某个适当子集。我们例子中的表已经是 2NF 了,因为每个候选键都是一个列。3NF 中的表意味着每个非键列在功能上也不依赖于其他一些非键列,因此创建了传递依赖. 有一个或一百个候选键并不重要。实际上它是 BCNF,而不是 3NF,它是关于功能依赖的“最终”范式。这是因为表可以在 3NF 中但不在 BCNF 中,因为可能有多个重叠的候选键。因此,当我们使用术语3NF来表示关于函数依赖性的“完全规范化”时,我们真正的意思是 BCNF。
如果我们要确保存储在数据库中的数据与我们在现实世界中确定的规则保持一致,不仅可以,而且必须是!
如上所述,该表是否符合 3NF(或更重要的是 BCNF)与其包含多少候选键正交。
不,仅仅因为确定表是否在 3NF 中与它有多少个候选键无关。相反,它与确保所有非键列在功能上完全依赖于这些候选键有关。
但这确实提出了一个有趣的观点。请注意,在 DBMS 中定义为约束的唯一键与概念业务模型中定义为业务规则的唯一标识符不同。也许在我们的世界中,我们总是知道这个人的 SSN,因此它作为一个人的候选键,也许我们还在我们称为Person Id的逻辑模式中引入了一个代理键。我们的商业模式包括规定 SSN 是我们这个世界上一个人的唯一标识符的规则。这意味着功能依赖此身份属性上的所有描述性属性。这条规则不会因为我们忘记或选择不通知 DBMS 而改变。这正是声明约束至关重要的原因——这样 DBMS 才能确保存储的数据符合业务模型的规则!如果我们没有在 SSN 上创建唯一约束,我们现在可能会无意中为具有相同 SSN 的同一个人创建多行;每一行都有不同的 Person Id!
Fabian Pascal 的Practical Database Foundation Series和 Chris Date 的Database Design and Relational Theory是关于这些主题的优秀入门书,这个答案就是从中得出的。虽然 Fabian 的每篇论文都是必读的,但论文 #1(明确定义了概念、逻辑和物理层面之间的区别)和论文 #4(明确定义了各种键)专门解决了这个问题。同样,Chris 的整本书都是必读的,而第二部分是专门讨论函数依赖性规范化的部分。
由于问题是基于对规则的解释,我们应该首先查看链接信息,即(强调我的):
我认为混淆是误解术语“候选键”的结果。一张表中可以有多个候选键。这就是为什么我们要在这个组中进一步指定修饰词:主要和备用。如果表可以有一个,而且只有一个,键,那么术语“主”键会产生误导,而应该被称为其他名称(可能是“父”或“来源”或“标识”等)。但是“主要”意味着可以有“次要”键,这些被称为“备用”键。
备用键通过唯一约束或唯一索引在物理模型中指示。还应该注意的是,两种类型的候选键(主键和备用键)都可以被外键引用(即使没有很好的理由通常不会/不应该做这样的事情!)。
不,因为这是物理与逻辑建模的问题。您可以拥有一个包含
IDENTITY
字段但尚未定义主键的表。表及其数据可以很容易地处于 3NF 中,即使物理模型不强制执行。这种区别类似于是否定义了外键。您肯定可以 JOIN 表,并且没有孤立记录,无论是否定义了任何 PK/FK。没有这些结构,数据可以 100% 正确。但是定义 PK 和 FK 是参照完整性(逻辑)和声明性参照完整性(物理)之间的区别。在物理模型中加入约束只是有助于执行逻辑模型的规则。关于 SSN(对于那些不熟悉该首字母缩略词的人来说是“社会安全号码”),它是一个备用键,并且有一个唯一的索引/约束:
我建议不要将 SSN 视为备用密钥并在其上放置唯一约束或索引,即使这样做很常见(SSN 通常被认为是“自然”密钥——现实世界中存在的密钥) . 主要有两个原因:
准确性:大多数时候,这些值是由填写表格的人输入系统的,无论是纸质表格还是在线表格。人们在输入数据时总是会犯错误,尤其是如果源是纸质表格,而该表格是由某人阅读别人草率的笔迹(例如我的,几乎无法辨认)输入的。
即使数据来自另一个系统,你能确定源系统验证了信息吗?你能确定他们的数据导出没有错误吗?如果您的数据导入出现错误怎么办?
唯一性:即使主要的社会保障管理局从未颁发过重复的 ID,这并不意味着没有发生重复。除了身份盗用问题之外,我记得几年前曾听人说过,他曾在美国税务局担任 DBA(我相信),并且必须处理社会保障福利,他们如何处理“问题”将死者的 SSN 重新分配给尚存的配偶(通常是寡妇)的旧做法,以便尚存的配偶更容易继续领取福利金。我敢肯定这种做法不久前就结束了,但“重复”数据仍在系统中。