在 SQL 表的第一范式 (1NF) 中,值不应重复,并且列应具有原子值。
我有一个表格,其中有列StartDate | 结束日期 | 持续时间。
StartDate 的值为 01/01/2000 和 EndDate 03/03/2003,因此持续时间为 2 个日期,01/01/2000 - 03/03/2003,使用 StartDate 和 EndDate 字段中相同的两个值。
我是否完全摆脱“持续时间”列并假设人们能够通过查询找到信息,或者是否有一种方法可以对其进行规范化以遵循规则而不丢失任何数据?
当我将这 3 列与其他信息分开到另一个表时,我在 3NF 点注意到了这个问题。
这应该在那之前完成吗?
如果 StartDate 和 EndDate 只是 Duration 中的日期,那么它在功能上确定它们,并且它们两者一起在功能上确定它。因此,标准化(保留 FD(函数依赖))到足够高的范式将使您将它们三个分离到一个单独的表中。
但显然,将 {Duration} 或 {StartDate, EndDate} 作为列的子集就足够了。如果添加其他属性,那就是多余的。规范化对此无能为力,因为它只能消除冗余,其中表可以被连接到表的投影替换。
一般来说最好存储区间终点。关系设计的一般思想是为您可能想要单独查询的某些事物的任何部分设置一个列。如果您想控制这种冗余,请了解计算/计算列。
PS 1 请参阅这个答案有关“原子性”。
PS 2. 规范化不是通过从规范形式移动到最高想要的形式来完成。 (应该是 5NF,然后出于某些原因可以进行反规范化。规范化为较低的范式可以排除良好的更高级别设计的出现。找到规范化为 3NF 或 BCNF 的算法。
我必须承认,我从来不太关心规范化形式,因为为了避免数据库中的冗余和不一致,你会自动应用它们,而不考虑 1NF、2NF 等。
使用您当前的表设计(3 列:StartDate、EndDate、Duration,也许还有其他列)满足 1NF,因为您无法将 StartDate、EndDate 或 Duration 拆分为有意义的部分。
如果我没记错的话,2NF 是关于主键的。我猜想,我们在给定的表设计中违反了 3NF。这是因为,如果我们有两条具有相同 StartDate 和 EndDate 的记录,它们将具有相同的 Duration,因此该字段并不单独依赖于某个主键。 StartDate 和 EndDate 也是如此。因此三列,我们可以删除一列来满足 3NF 要求。您可以自由选择。
我的观点是 - 没有人能够说在表中包含所有 3 个字段(开始日期、结束日期或持续时间)是一种不好的做法。