《SQL与关系数据库理论——如何编写健壮的SQL代码》一2.3 数据值原子性

简介: 本节书摘来华章计算机《SQL与关系数据库理论——如何编写健壮的SQL代码》一书中的第2章 ,第2.3节 C. J. Date 著 单世民 何英昊 许侃 译 更多章节内容可以访问云栖社区“华章计算机”公众号查看。</span> 2.3 数据值原子性 希望前面一节能使你确信域实际上就是类型。

本节书摘来华章计算机《SQL与关系数据库理论——如何编写健壮的SQL代码》一书中的第2章 ,第2.3节 C. J. Date 著 单世民 何英昊 许侃 译 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.3 数据值原子性

希望前面一节能使你确信域实际上就是类型。现在我要转到数据值原子性以及相关的第一范式概念(简称为1NF)。在第1章中,我说过1NF意味着每个关系的每个元组在每个属性的位置都只包含一个(正确类型的)单一值,并且通常会说那些“单一值”应该是原子的。但是后面这个要求就引出了一个显而易见的问题:“数据是原子的”指的是什么?
在前面提到过的《The Relational Model for Database Management Version 2》第6页,Codd将原子性数据定义为“不能被(排除某些特殊功能的)DBMS分解为更小片段”的数据。然而,即使我们忽略括号中的例外,这个定义也还是有点令人迷惑;起码,它肯定不是很精确的。比如,字符串会如何?字符串是原子的么?我所知道的每种数据库产品都提供了大量在定义上就依赖于字符串通常可以“被DBMS分解为更小片段”这一事实的运算符(LIKE、SUBSTR(子串)、“||”(连接),等等)。那么,这样的字符串是原子的么?你怎么认为?
下面还有一些取值示例,它们的原子性至少是开放问题,而我们又确实想让它们作为关系中元组的属性值:

  • 位串;
  • 有理数(可分解为整数和小数);
  • 日期和时间(可分解为年/月/日和时/分/秒分量)

等等。
现在给出一个更让人吃惊的例子。图2.1中的R1关系是我们的运行示例中出货关系的简化版本,它说明了某个供应商供应某种零件,并且对每个合法的(SNO,PNO)组合都包含了一个对应的元组。从此例的角度出发,我们认为供应商编号和零件编号就是“原子的”;这样就可以假设R(至少)是符合1NF的。
image

图2.1:R1、R2和R3的关系
现在假设我们使用R2替换R1。R2显示了确定的供应商供应确定的零件组(R2中的PNO属性被有些作者称为多值属性,这个属性的取值是零件编号的组)。于是大多数人当然会说R2不属于1NF;总之,它看来像一个“重复组(repeating groups)”的实例。重复组是几乎人人都赞成1NF应该禁止的东西(因为这样的组是明显非原子的)
好了,为了论证我们认定R2不属于1NF。但是假设我们现在用R3替换R2,那么我要说R3是属于1NF的!注5不妨考虑一下:

  • 首先,注意属性已重新命名为PNO_SET,而且我也说明了零件编号组是使用大括弧包围的PNO_SET值,以强调每个这样的组都是单一值:一个集合值。无疑,在某一抽象级别上,一个集合仍是一个单一值。
  • 其次,不管你对第一个论证有什么想法,事实是从可分解性来看,一个像{P2,P4,P5}这样的集合和一个字符串没什么区别。和字符串类似,集合有内部结构;然而,正如字符串的情况,集合通常为了某种目的而忽略内部结构。换句话说,如果字符串符合1NF的要求(即字符串是原子的),那么集合也必须是符合的。

这里真正要说的是:原子性概念并不是绝对的;它依赖于我们到底要怎样处理数据。有时,我们要将一个零件编号集合的整体作为一个事物来处理;有时我们又要将集合中的各个零件编号分别处理——不过此时我们降到了一个更为底层的细节级别,或者一个更为底层的抽象级别。下列类比可能会有帮助。在物理学科(毕竟原子性术语的起源于此)中情况是完全相同的:有时我们会将单个原子看成不可分割的,而另一些时候又会考虑构成原子的亚原子微粒(比如,质子、中子和电子)。进一步讲,至少质子和中子也不是真正不可分的,它们还包含各种称为夸克的亚亚原子(subsubatomic)颗粒。
让我们暂时先回到关系R3。在图2.1中, PNO_SET显示为一般集合。但实际上如果它们具体化为关系会更有用(在图2.2中属性名称变为PNO_REL)。为什么会更有用?因为关系模型(而不是一般集合)关注的是关系。注6这样的话,就可以对关系全面使用关系代数——可以对它们进行选择、投影、连接等等。相反,如果我们使用一般集合代替关系,那么我们就要引入新的运算符(集合并、集合交等等)来处理那些集合……尽可能重用已有运算符应该更好吧!
image

图2.2:R4的关系(从R3导出)
术语:图2.2中的PNO_REL属性是一个关系值属性(relation valued attribute, RVA)。当然,与其对应的域也是关系值化的(即构成域的值是关系)。在第7章中,我会更详细地说明RVA;这里我只想强调SQL并不支持RVA。(确切地说,SQL不支持RVA的等价物——表值列(table valued columns)。然而, SQL支持取值是数组的列,取值是多行的列,甚至取值是“行的多重集(multisets of rows)”的列。多重集,又名包(bag),它和集合很类似,只不过它允许重复。注7以行的多重集作为取值的列多少有些像“表值列”;但是,它们并不是表值列,因为从定义上说它们所包含的值不能使用正常的SQL表运算符进行运算,因此不是正常SQL表值。)
其实,上面的例子是我精心挑选出来的,因为它很有冲击力。毕竟,有关系值属性的关系看起来像有重复组的“关系”,而在关系世界里你可能总是听别人说重复组是万万不行的。但是,我有诸多示例可以证明我的观点。我可以举出包含数组的属性(因此也有包含数组的域);或包含包(多重集)的属性(或域);或包含列表的,包含图片的,包含音频或视频的,包含x射线的,包含指纹的,包含xml文件的,包含任何你能想到的其他类型、“原子的”或“非原子的”的值。属性(以及域)可以包含任何东西(即任何值)。
需要注意的是,你可能会想起几年前经常听到的所谓“对象/关系”系统。前面的段落花费了大量篇幅解释为什么一个真正的对象/关系系统实际上就是一个真正的关系系统——也就是一个支持关系模型、且具有对象关系支持能力的系统(毕竟,从用户视角来看,一个对象/关系系统的关键就是我们可以在关系中使用任意复杂的属性)。或许,一个更好的表述方法是:一个正规的对象/关系系统就是一个具有正规类型支持能力的关系系统(尤其是正规的用户定义类型的支持)。这也意味着它就是一个正规的关系系统。同样的,被一些人津津乐道的所谓“对象/关系模型”也不过是关系模型。

相关文章
|
8天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
51 10
|
20天前
|
SQL 存储 关系型数据库
一文搞懂SQL优化——如何高效添加数据
**SQL优化关键点:** 1. **批量插入**提高效率,一次性建议不超过500条。 2. **手动事务**减少开销,多条插入语句用一个事务。 3. **主键顺序插入**避免页分裂,提升性能。 4. **使用`LOAD DATA INFILE`**大批量导入快速。 5. **避免主键乱序**,减少不必要的磁盘操作。 6. **选择合适主键类型**,避免UUID或长主键导致的性能问题。 7. **避免主键修改**,保持索引稳定。 这些技巧能优化数据库操作,提升系统性能。
215 4
一文搞懂SQL优化——如何高效添加数据
|
1月前
|
SQL 数据可视化 数据处理
使用SQL和Python处理Excel文件数据
使用SQL和Python处理Excel文件数据
52 0
|
8天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
66 6
|
29天前
|
SQL XML Java
整理几个常用的sql和其他代码
整理几个常用的sql和其他代码
11 1
|
30天前
|
SQL 安全 数据库
第三章用sql语句操作数据
第三章用sql语句操作数据
10 0
|
1月前
|
SQL 数据库 数据库管理
SQL中如何添加数据:基础指南
SQL中如何添加数据:基础指南
24 2
|
1月前
|
SQL 存储 关系型数据库
【MySQL】——关系数据库标准语言SQL(大纲)
【MySQL】——关系数据库标准语言SQL(大纲)
55 0
【MySQL】——关系数据库标准语言SQL(大纲)
|
2月前
|
SQL 数据库 数据安全/隐私保护
sql注入碰到加密数据怎么办
sql注入碰到加密数据怎么办
19 1
|
2月前
|
分布式计算 资源调度 Hadoop
Flink报错问题之Sql往kafka表写聚合数据报错如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。