Codd 最初似乎意味着没有值本身就是一个集合。这是一个有用的起点,但“原子”在涉及数据库时没有本体论意义(CJ Date 指出的一点是正确的)。Codd 试图将定义形式化为不能在特殊数据库操作之外进一步分解的东西(即时间戳是原子的,因为提取年份是一个特殊的数据库操作)。换句话说,如果数据库可以分解出子值,那就可以了。但是您不应该有需要应用程序逻辑分解的集合(无序列表)或对象。
随着时间的推移和在操作环境中与这个问题的斗争,我会提出一个原子性的中间定义,它比 Codd 更严格,并且没有 Date 讨论的兔子洞:
对于第一范式而言,值是原子的当且仅当:
该值不是一个集合(是的,我知道 Date 不同意)并且
没有对该字段的任何子部分的外键引用。
特别是,一个值的表示不能确定它的原子性。将 IP 地址表示为 "10.0.0.1" vs ARRAY[10,0,0,1] vs 167772161 对于 1NF 分析并不重要,因为这三个都指的是相同的原子值。
1NF 要求每个关系中每个元组中的每个属性位置都包含适当类型的单个值。类型可以任意复杂。事实上,类型可以是关系。(CJ Date 的书《深入研究数据库:从业者的关系理论》以一种非常容易理解的方式处理了这个问题。)
“原子”从来没有真正意味着“不可分割”,这就是为什么这个词最终失宠的原因。粗略地说,“原子”意味着如果一个值具有组成部分,则 dbms 要么忽略这些部分的存在,要么提供操作它们的函数。例如,时间戳值具有这些部分。
这种价值显然是可分割的,所有的数据库管理系统都提供了操作这些部分的功能。它们还提供了一种选择时间戳作为单个值的方法。(当然,确实如此。)
“原子”指的是 Codd 从 1969 年开始的原始概念,即关系中每个元组中的每个属性都应该由单个值组成,并且不允许像 CODASYL 模型这样的数据库支持的那种多值结构。
在现代 SQL DBMS 中,原子性并不是真正的问题。SQL 表不允许多值列,并且值始终是“原子的”。
原子意味着无法进一步划分的数据。
原子性规则:
像 fullname 列不能说它可以是原子的,因为它可以进一步划分为 lastname,firstname。感兴趣的列也可以进一步划分,因此不能划分的列称为原子列。
Codd 最初似乎意味着没有值本身就是一个集合。这是一个有用的起点,但“原子”在涉及数据库时没有本体论意义(CJ Date 指出的一点是正确的)。Codd 试图将定义形式化为不能在特殊数据库操作之外进一步分解的东西(即时间戳是原子的,因为提取年份是一个特殊的数据库操作)。换句话说,如果数据库可以分解出子值,那就可以了。但是您不应该有需要应用程序逻辑分解的集合(无序列表)或对象。
随着时间的推移和在操作环境中与这个问题的斗争,我会提出一个原子性的中间定义,它比 Codd 更严格,并且没有 Date 讨论的兔子洞:
对于第一范式而言,值是原子的当且仅当:
特别是,一个值的表示不能确定它的原子性。将 IP 地址表示为 "10.0.0.1" vs ARRAY[10,0,0,1] vs 167772161 对于 1NF 分析并不重要,因为这三个都指的是相同的原子值。
特别是,关于原子性的常见(有时是有用的!)1NF 违规包括:
这些问题或多或少会产生相同的数据异常。
这意味着无法分解密钥。假设您有一个包含三列的表,分别是名字、姓氏和电话号码。您在 (forename, surname) 上声明复合主键。该主键不是原子的,因为它实际上由两列组成。现在假设您将表更改为两列,全名和电话号码,主键为全名。钥匙现在是原子的吗?不,因为在您的应用程序中,您仍然可以在空间上将其拆分为名字和姓氏。现在让我们将表id、full_name 和telephone_number 设为id 上的主键(它是一个整数)。那是原子的,因为整数不能被有意义地分解。
考虑地球上的一个位置。我可以使用(经度、纬度)对或 HTM(分层三角网格)代码找到它。因为它们都测量相同的数据。这是一个物理事实,我们可以用手机测量;它为您将网格编号转换为 [经度,纬度]),它们在您的模型中必须是原子的或复合的。
不要将用于测量的比例和用于显示数据的符号与数据的性质混淆。
“原子”只是指任何不是关系的东西。1NF 是关于消除具有作为元素的关系的域。任何不是关系的东西都可以作为值。
原子值仅就关系代数而言是原子的,例如,您不能以分解关系的方式投影或选择原子值的一部分。
这并不意味着原子值是严格不可分割的——例如,数据库可能具有选择字符串的子字符串的功能。但这需要特殊功能。您不能仅使用 SELECT 或 WHERE 来分解字符串,就像对表一样。
原子键是一种不能分解的主键。这意味着这个键没有被进一步划分,如学生ID,员工ID。