Man*_*ngo 10 normalization database-design relational-theory
我试图获得什么是第一范式的明确版本。我阅读的所有内容都略有不同。
许多权威,例如 Date,说根据定义,关系总是处于第一范式,而其他人则给出了要求列表。这意味着对 1NF 的要求从零到很多。
我想区别在于表和关系之间的区别:表可能是一团糟,而关系遵循某些限制。关系在 SQL 中表示为表的事实因此造成了一些混淆。
我特别关注 1NF,因为它与 SQL 数据库有关。问题是:需要什么属性来确保表处于第一范式?
许多权威建议,如果一个表代表一个关系,那么它已经在 1NF 中。这将 1NF 的定义推回到关系的定义。
以下是 1NF 中表的一些属性:
[1] 技术上属性是无序的,但在表格中,行数据必须与列标题的顺序相同。然而,实际的顺序是微不足道的。
在多个数据上:
原子数据的概念是一个项目不能被进一步分解。这个概念是有限制的,因为虽然从技术上讲,一切都可以令人厌烦地分解,但实际上不能进一步分解所讨论的数据,这取决于数据的使用方式。
例如,完整地址或全名通常应该进一步细分,但可能不应该进一步细分诸如给定名称或城镇名称之类的组件,尽管它们可以作为字符串。
至于重复的列,它是一个设计不良列具有近重复列,例如phone1
,phone2
等。通常,重复数据指示用于一个附加的相关表的需要。
依赖
行之间不应该有任何关系,除了它们符合相同的标题。
列之间也应该没有关系,但我相信这是更高范式的主题。
问题是:1NF 的定义中有多少上述内容?独立行位也进入了吗?
范式的定义(从 1971 年“数据库关系模型的进一步规范化”的介绍中被称为第一范式)和关系范式本身的定义于 1970 年发表在科学论文中,提供了强有力的支持。数据库管理实践的基础,即“大型共享数据库数据的关系模型”(简称 RM),由EF Codd 博士创建,他是图灵奖获得者和关系框架方面的权威。
是的,关于 Codd 博士的文本有很多解释、解释、阐述、偏差和观点,但我个人更喜欢坚持原始来源,我强烈建议你自己分析,这样你才能得出自己的结论。
我当然不完全了解 RM,但我对它的了解使我能够欣赏它的卓越、远见、意图和范围,尽管几十年后人们会注意到它有一些轻微的不精确,但它们并没有减少,无论如何,它的天才和优雅。在其领域,RM 以独特的方式经受住了时间的考验,并且仍然无与伦比。
强调上述不精确的行为——使用慈善术语——是不公平的,因为从相当远的地方看,这种开创性的材料需要一些改进和扩展,是的,但作品的主体从一开始就坚如磐石。非常构想(而且,事实上,科德博士本人对这种改进和扩展做了大部分——如果不是全部的话)。
我继续不断地重读 RM 以加强我对这个特殊知识来源的理解(每次重读我对它的尊重都会增加);目标是站在巨人的肩膀上。
需要注意的是,由于关系是抽象资源,Codd 博士设想了以表格形式表示它们的效用(他最初使用术语“数组表示”,但后来使用了“表”或“r-表”),因此关系数据库 (RDB) 的用户、设计者和管理员可以以更熟悉或更具体的方式来接触他们。因此,在 RDB 实现的上下文中,使用table作为关系的简写是有效的,只要所述表代表实际关系即可。这个特征——尽管很明显——非常重要,因为在评估一个表是否表示符合第一范式 (1NF) 的关系之前,它必须准确地表示一个关系。
RM 自然包含一张表必须具备的特性,以确定它是否真的描绘了一种关系,但我将在此处提供一种关于它们的非正式和朴实的解释(另一个,是的!):
拥有一个实际上代表关系的表是至关重要的,因为当它经历关系类型的操作操作时,结果又是一个代表关系的表。以这种方式,所述表的行为是可预测的。
在 RM 的第一部分中,Codd 博士展示了几个关系示例以介绍一些概念;因此,为了理解atomic domain的含义,让我们从下面的 RM 摘录开始,其中详细介绍了一些相关要点:
到目前为止,我们已经讨论了在简单域上定义的关系的例子——元素是原子(不可分解)值的域。可以在关系框架内讨论非原子值。因此,某些域可能具有作为元素的关系。反过来,这些关系可以在非简单域上定义,等等。
通过这种方式,可以说上述每个说明关系都适合两种类型之一,例如A 类或B 类:
种类 A只对由域(列)构成的关系(表)进行分组,这些域(列)在每个元组(行)中只包含简单的值,即,这样的域(列)不包含作为值的关系(表),在这个上下文意味着这些值是原子的,因为它们不能连续分解成新的关系(表)。因此,此类的关系是规范化的,即它们符合 1NF,它们的形式是可取的。
类型 B由具有一个或多个域(列)的关系(表)专门集成,这些域(列)将关系保存为每个相应元组(行)中的值,这表示所述值是非原子的,因为它们随后可以分解为新的关系(表格),即它们是可分解的。因此,这种关系是非规范化的,即它们违反了 1NF,它们是一种不受欢迎的形式。
Codd 博士通过以下段落介绍了 RM 中的规范化部分:
域都是简单的关系可以在存储中由上面讨论的那种二维列齐次数组表示。与一个或多个非简单域的关系需要一些更复杂的数据结构。出于这个原因(以及下面将引用的其他原因),消除非简单域的可能性似乎值得研究!事实上,有一个非常简单的消除过程,我们称之为归一化。
然后他继续展示:
一组未规范化的关系(它具有包含关系作为值的域,即它们是非原子的;即它们是非简单的)
一组归一化的关系(即一个被分解的关系;即一个关系值域被分解为简单的域,这意味着它们是原子的)
然后他描述了从非规范化关系中获得规范化关系的过程。
在这方面,他用来说明规范化练习和练习描述本身的关系非常清楚,我再次建议你自己分析它们(我也希望这能鼓励一些读者参与文本)。
他接连指出:
标准化类型的进一步操作是可能的。这些不在本文中讨论。
而上述操作,即第二范式和第三范式(2NF和3NF)其实在“Further Normalization of the Data Base Relational Model”中有详细介绍,并且如上所述,在这篇论文的介绍(以及后来的印刷和出版)之后,原来的范式被称为第一范式。
从业者可以观察到,具有非规范化关系(表)会在 RDB 实现中引入(几乎总是不必要的)卷积。
满足 1NF 的关系简化了约束和数据操作操作的定义,可以通过比非规范化关系(表)所需的数据子语言更简单的数据子语言来实现,正如 Codd 博士在以下几行中指出的那样:
如上所述,采用关系数据模型允许开发基于应用谓词演算的通用数据子语言。如果关系的集合是范式的,则一阶谓词演算就足够了。这种语言将为所有其他提议的数据语言提供语言能力的衡量标准,并且本身将成为嵌入(通过适当的句法修改)各种宿主语言(编程、面向命令或面向问题)的有力候选者。[…]
[…]
数据子语言的通用性在于它的描述能力(而不是它的计算能力)。
困惑
从我的观点来看,困惑出现了,由于(a)中上述的过量的解释,解释等等,关于1NF和所述RM本身,因为(b)的进一步尝试重新定义1NF该状态具有关系对于包含值的域,反过来,关系符合1NF,只要它们是每个相应元组的一个值。
行之间不应该有任何关系,除了它们符合相同的标题。
我不确定我是否正确理解了该语句的意图,但是,除了符合相同的标题外,关系(表)的(元组)行之间必须存在连接,因为它们中的每一个都应该是关于一个的断言关系(表)应该表示的特定实体类型(根据感兴趣的业务上下文定义)的特定出现。
列之间也应该没有关系,但我相信这是更高范式的主题。
我也不知道我是否正确解释了该语句的含义,但事实上,根据我对前一个方面的回应,关系(表)的域(列)之间也必须存在关系,这正是为什么它是一个关系(关系模型和具体 RDB 实现的基本结构)。
举例说明,关于假设关系(表)
Salary (PersonNumber, EffectiveDate, Amount)
元组(行)
Salary (x, y, z)
会传达意思
The Salary payed to the Person identified by PersonNumber x, on EffectiveDate y corresponds to the Amount of z
因此,Salary
关系(表)的每个元组(行)都必须符合上面所示的断言结构,区别在于替换了相关域(列)值,但(a)之间必须存在关系所有Salary
域(列)以及(b)它们与每个元组(行)的所有对应值之间;这样的关系实在是少不了。
更高的范式(2NF 和 3NF)对于摆脱关系(表)的域(列)之间的函数依赖性很有用,它们有助于避免域(列)之间的不良 连接,因为所述不良连接允许引入更新异常. 2NF 和 3NF 都有助于测试某个 RDB 实现中关系(表)结构的健全性。
一个例子。取一个包含典型美国地址的文本字符串:
"123 Cornhusk Rd., South Succotash, NY 12345"
Run Code Online (Sandbox Code Playgroud)
编写查询来查找 Cornhusk Road 的所有居民或 South Succotash 镇或纽约州的特定居民将是一项艰巨的任务。特别是当数据中有以下字符串时:
"123 Cornhusk Road, South Succotash, NY 12345"
"123 Cornhusk Rd., South Succotash, New York 12345"
"123 Cornhusk, South Succotash, NY 12345"
"123 Cornhusk Rd., SOUTH SUCCOTASH, NY 12345"
Run Code Online (Sandbox Code Playgroud)
其中每一个都指定相同的实际地址(这甚至不考虑像“Succatash”这样可能的拼写错误),但编写算法来成功比较它们是我不想将我在地球上的最后几年奉献给你的事情。
输入第一范式。我不会详细介绍它是如何完成的,只需考虑大多数数据库中常见的形式:
create table Addresses(
...
Street varchar,
City int references Cities( ID ),
State char( 2 ) references States( ID ),
Zip int
...
);
Run Code Online (Sandbox Code Playgroud)
这并不是完全的正常化。例如,您可以将 Street 进一步划分为 StreetNum 和 StreetName,但这对于一个简单的说明来说已经足够了,而且它确实与现实生活中所采用的规范化过程有关。找到 Cornhusk Road 的所有居民还有一个小问题,但如果你在 Street 中搜索子字符串“Cornhusk”,并且在某个地方碰巧有一个名为 Cornhusk 的城镇,至少不会造成混乱。
Date 等人提供的定义的问题在于,他们未能查看数据的内部并考虑该数据的含义。并不是我特别责怪他们,这可能相当困难。
所以我们必须把一个“字符串”变成一个“地址”。但提出一个包罗万象的地址定义并不像看起来那么简单。尤其是在使用多个国家/地区的地址时。
首先,我们修复上下文。没有上下文,任何事物都没有意义。我们这里的上下文是地址。在该上下文中,我们可以看到具有特定含义的部分数据,例如Street、City等。我们为每个含义分配一个单独的字段。
困难之处在于,数据就像文字一样,对不同的人可能有不同的含义,或者有些人可以看到其他人看不到的含义。它可能是一个完全独立的项目,需要大量的合作努力。但它是良好数据库设计的关键要素。
标准化的目的是消除或至少最小化异常数据。请考虑这样一个事实:在上表中,可能输入的城镇或邮政编码在所选州中不存在。或者输入的街道实际上并不存在于所选城镇中。啊,但现在我们正在进入第二和第三范式,这是另一个话题。