尽管在关系数据库中是一个基本概念,但第一个正常形式(或1NF)通常会令人难以置疑或彻头彻尾地解释。这篇文章解释了1NF实际意味着什么,并且是有用的,并且揭穿了一些误解。
E. F. Codd,关系模型的发明者,解释为:"消除与元素和#34的关系的域名;在更常见的数据库术语中,这意味着"消除可以将表作为值&#34的列;
由于SQL不允许创建或使用嵌套表,因此大多数关系数据库将以必要性地处于第一个正常形式。
无情的形式| |消除域名与元素有关系🡓First正常形式| |消除非全依赖|非Prime属性在|候选键🡓秒正常形式| |消除及物依赖非Prime属性在|候选钥匙🡓第三常规形式
关于术语的注意事项:关系模型的基本前提是将数据视为关系。与表格或多或少的关系(常见的误解是关系是指表格之间的关系),属性对应于列,域 - 1NF中的关键概念 - 对应于列的数据类型。
行必须是独一无二的。虽然某些数据库允许重复的行,但这不是根据关系模型的。在实践中,通过定义表的主键来确保。
行不能有任何内在的订单。如果一组行的顺序很重要,则该订单必须表示为值(例如,AN"订单"列)
关系具有固定数量的属性(列),每个列都有一个域,它定义了允许的值。
因此,即使在不正常的形式中,数据也必须符合某些约束被视为关系。但是域没有限制。由于域可以包含任何内容,它们也可以包含关系。这意味着属性可以与价值有关系,并且该关系可以具有与价值和依此类推的关系。
但Codd实现了数据模型和查询语言,如果消除嵌套关系,则可以显着简化。他建议将嵌套关系转换为独立关系的正常化过程,通过外键而不是通过遏制引用父行的独立关系。
对于现代读者来说,嵌套关系的情况可能似乎是一个相当模糊的特殊情况。为什么甚至花了这么多关注?但在上下文中,编码正在写作是一个重要的问题。
主导数据库模型在关系模型之前的年龄是分层数据库模型。在分层模型中,记录可以包含一组子记录 - 称为重复组或表值属性。
如果分层数据库直接转换为关系模型,则这些嵌套记录组将直接转换为关系值属性。但嵌套结构会严重破坏关系模型的好处。因此,Codd花了一些努力证明"正常形式"并解释规范化的过程。
1NF中的关系可以以二维阵列的形式呈现,存储和交换。嵌套关系需要更复杂的数据结构。
数据语言需要复杂的路径导航语法,以便明确地定位嵌套关系中的数据项。在1NF中,可以仅通过关系名称,属性名称和主键来识别所有值。
对数据语言的影响非常重要。特别是Codd在引入关系代数之前引入1NF,这是SQL等数据语言的理论基础。这就是SQL不支持嵌套关系的原因!
好奇的现象是,1nf在这么多的高调的地方误导了。作为一个实验,我谷歌入"第一个正常形式"并发现了一堆解释和教程。前两页结果的所有结果都有不正确的解释 - 包括在维基百科的第一次击中。 [编辑:现在已经提高了对维基百科的解释。]
误解可能是因为互联网上的原始文件不容易访问,并使用今天不容易理解的术语。这似乎已经转了1nf解释了一个电话的游戏,其中误区复制和发展。
一个主要的混乱来源是用词"原子和#34; - 一旦,在特定的背景下。不幸的是,很多作者都锁在这个词上并忽略了上下文。
到目前为止,我们已经讨论了在元素是原子(非分解)值的简单域名上定义的关系的示例。可以在关系框架内讨论非仿真值。因此,一些域可以与元素有关系。反过来,这些关系可以在非限制性域中定义,等等。
我肯定如果Codd知道这段经文的混乱,他可能已经使用了更清晰的语言。然而,含义很清楚:非仿真值是关系,原子值是不是关系的任何东西,因此是关于关系运营商的原子。
许多解释(包括维基百科)使用逗号分隔的字符串的示例,其中包含电话号码作为1nf冲突的示例:
毫无错误地,在单个字符串中编码多个值通常是一个不好的设计。但它与第一正常形式无关。第一个正常形式意味着列不应允许关系为值。逗号分隔的字符串仍然只是数据库类型系统的透视图中的单个字符串。
每个单独的字段应保持最小的数据元素,以便于易于排序和搜索。例如,日期列可以分为日,月和年份。
但是约会不是关系(你可以' t添加新"行"到达日期!)。标准化的CODDS示例实际上包括被视为原子的日期。
列中的数据分解为最小的有意义的元素。名称列将分为三列作为名字,中间名和姓氏。
当然,如果是,它可能会将名称分解为组件需要e.g.按姓氏排序。 (它还开启了国际名称的蠕虫。)但这是业务需求的问题,而不是1NF。只要名称类型不是关系,它就好了。
在Codds的归一化的典范中,他甚至有一个"姓名"作为单一列。
另一个混淆来源是一个地方的CODD关于重复组。如前所述,重复组是来自分层数据库的术语,其描述在父记录下嵌套的一组记录。 Codd将其定义为等效于非简单域,即关系valued属性。
表不应该重复一组列,例如Customer1name,Customer2name和Customer3name。
这样的表可能是一个例子糟糕的设计或至少列命名的一个例子。特别是如果客户的数量可能会改变!但多个列具有相同类型本身的列没有错,只要它们具有不同的名称。例如,婚姻证书的表可能有列法1和派对2,这会很好。
在任何情况下,这与1NF的问题无关,因为每个单独的列都有一个简单的域。
重复属性通常称为重复组,是固有的不同属性。在满足第一正常形式要求的实体中,每个属性都是独立的,并且在其含义和名称中是唯一的。
这种情况违反了第一个正常形式的要求,因为january_salary_amount,fechuary_salary_amount,以及march_salary_amount基本上是相同的属性,employee_ lonting_salary_amount。
这个定义铰链在&#34的非常模糊的概念上;基本相同"我不认为以上解释使任何逻辑意义 - 1月份和2月薪水显然是不同的。
下一步是确保没有重复数据组。考虑我们有下表(...)
但根据1NF,我们需要确保没有重复数据组。所以,让我们将上面的表格分成两部分,然后使用键加入它们......
上表显然是无效的,因为主键不是唯一的,但"重复数据"本身并不是一个违反1NF。 1NF不关心仅限类型的值。 (上面的表可能是违反第三正常形式的违规。)
Codd显示了消除嵌套关系的直接进程:您将嵌套关系转换为顶级关系,然后添加一个外键参考"父行和#34;从哪里提取。 (这当然需要所有表都有一个主键 - 具有主键是标准化的必要前提条件)
但是许多教程展示了一个奇迹的过程。典型的例子是学习的。他们从这个表开始:
这是奇怪的,因为你会期望roll_no是主要键,但显然它是不是我们现在有重复的。如果我们被遵循了Codd'■刚刚将设置提取到单独的表,我们将有两个表:
这将是更逻辑的,不打破主键,并完全归一化。
一些解释为具有主键的1nf定义。 这是一个相当良好的误解,因为它不会导致任何人做出不良的设计决策。 但技术上,它是不正确的。 具有主要键是对第一种正常形式归一化的先决条件。 CODD,E.F(1970)大型共享数据库的数据关系模型。 CODD,E. F.(1971)关系模型的进一步正常化。