假设我们有一个名为Widget的对象,我们可以为此构建一个数据库表。
现在,假设我们有两套的其他细节来描述小部件。每组数据都可以在单独的时间获得。所以,假设我们的小部件在其生命周期中有三个阶段......
在第1阶段中,我们只是拥有一个名称和描述的小部件。
widgets
-------
id (PK)
name
description
在阶段2 中,我们的小部件获得高度和重量。
widgets
-------
id (PK)
name
description
height
weight
在第3阶段中,我们的小部件可获得目的地和运费。
widgets
-------
id (PK)
name
description
height
weight
destination
shipping_cost
上述模式(对于“阶段3”)意味着阶段1或阶段2中的窗口小部件的数据库记录将具有空值。
或者,我们可以构造一个永远不会有空值的模式(但是父记录可能有零个,一个或两个子记录,具体取决于小部件生命周期的当前阶段):
widgets
-------
id (PK)
name
description
widget_specs
-------
id (PK)
widget_id (FK)
height
weight
widget_delivery
-------
id (PK)
widget_id (FK)
destination
shipping_cost
这些替代方案中的一个总是正确的吗?各自有正当的利弊吗?如果答案取决于更多的变量,它们是什么?在什么条件下,一种替代方案会成为明显的首选方式?
接受的答案将引用一个关于该主题的现代权威来源。
编辑:我觉得这很容易引发争议,但这也是一个应该有正当理由的话题。缺点,因此是一个权威的答案。这个问题只是一个让我烦恼的问题,因为我已经看到它在没有正当理由或考虑替代方案的情况下完成了两种方式。根据当前引领潮流的DBA类型,我只想知道哪个正确。
答案 0 :(得分:2)
普通表格(BCNF / 5NF)通常是数据库设计最合理的基础,除非您找到令人信服的理由偏离它。这意味着应该首选没有空值的模式。归一化减少了冗余数据和异常的可能性,并最大限度地减少了设计中内置的“偏差”,使其更易于维护和扩展。
Null使数据库上的大多数操作复杂化并导致某些查询的结果不正确。只有在您发现某些特殊原因的设计中添加空值 - 通常这些原因与DBMS限制有关,这些限制不允许您在不使用空值的情况下轻松实现某些约束或其他逻辑。还要记住,每当数据库设计人员将空值添加到数据库中时,应用程序设计人员通常必须做额外的工作来删除或隐藏它们,以便最终用户受益。
您可以在Fabian Pascal的“数据库管理中的实际问题”和Chris Date的书籍以及EFCodd,Witold Lipski和其他许多人的论文中找到有关空值和其他问题的广泛讨论。
答案 1 :(得分:1)
缓解空列的选项是创建一对一的关系,或者小部件可以有多个权重&交货规格?
这也意味着你必须LEFT JOIN到两个支持表来检查信息,其中单个表不需要任何特殊的东西(除了在某些情况下的IS / IS NOT NULL检查)。
一对一的关系是一种性能优化,但这并不是你问这个问题的原因......