《SQL与关系数据库理论——如何编写健壮的SQL代码》一3.1 元组是什么

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

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

3.1 元组是什么

下面这个是元组么?
image

不,它不是元组,它是一个元组的图示,但不是元组(本章唯一一次把类型名称和属性名称一起放到图示中)。在第1章中我们看到,一个“事物”和“事物的图示”是有逻辑区分(logical difference)的,而这个区分非常重要。比如,元组对于其属性是没有自左至右排序的,所以下面的图示对于刚才那个元组是同样好(或者同样坏?)的。
image

因此,尽管我在后面会使用很多与这些图示相似的图示,但要记住它们只是“图示”而已,而它们有时可能会给出错误的暗示。
在此告诫之后,现在给出元组精确的定义如下:
定义 设T1, T2, ? Tn (n ≥ 0)为可以同名的类型名称。与每个类型Ti对应,存在相互区别的属性名Ai;形成的n个属性名/类型名组合均为属性(attribute)。对应于每个属性,存在类型为Ti的属性值(attribute value)vi与其关联;产生的n个属性/值组合均为一个分量(component)。则,依此定义的所有n个分量的集合(设为t),即是涵盖属性 A1, A2, …, An的一个元组值(tuple value)(或简称为元组)。值n为t的度(degree);度为1的元组为一元元组(unary),度为2的元组为二元元组(binary),度为3的元组为三元元组(ternary),…。更一般的,度为n的元组为n元元组(n-ary)。由所有n个属性构成的集合为t的标题(heading)。
以上文中对应S1供应商的两个图为例,对于第一张图有:

  • 度为4。对于标题也可说其度为4。
  • 类型名(如图所示,自左到右)包括CHAR 、CHAR 、INTEGER、CHAR。
  • 对应的属性名称包括SNO 、SNAME、STATUS、CITY。
  • 对应的属性值为'S1'、'Smith '、20、'London'。注意此处用来封闭字符串的引号;我在图中并没有使用这样的引号,但我或许应该这么做,因为这样更为正确。
  • 标题:这里最简单的就是显示另一幅图示:

image

显然,这幅图示表示一个集合,并且属性的顺序是任意的。下面是相同标题的另一图示:
image

练习:我们可以画多少个本质上一样的不同图示来表示这个标题?(答案:4!=4×3×2×1 = 24.)注1
一个元组是一个值;因此,和所有的值一样,元组也有一个类型(第2章中已介绍过),而此类型像所有的类型一样也有名称。在Tutorial D中,这样的名称采用tuple {H}的形式,其中{H}为标题。在我们的示例中,元组类型的名称为(其中的属性顺序是任意的):

TUPLE { SNO CHAR , SNAME CHAR , STATUS INTEGER , CITY CHAR }

再说一遍,一个元组是一个值。因此,元组像所有的值一样也必须由某个选择器调用返回(如果返回值是元组,自然应该是一个元组选择器调用)。下面是针对示例的一个元组选择器调用(还是用Tutorial D,分量的排序也是任意的):
TUPLE { SNO 'S1' , SNAME 'Smith' , STATUS 20 , CITY 'London' }
注意,在Tutorial D中,每个分量都指定为“属性名/表达式”对。其中,指定的表达式表示对应的属性值;省略了属性类型,因为它总是可以从指定表达式的类型推导得到。
另一个示例如下(不同于前例,此例中不是字面值,因为不是所有的参数都设定为文字):

TUPLE { SNO SX , SNAME 'James' , STATUS TX , CITY CX }

此处假定SX、TX和CX分别为CHAR、INTEGER 和CHAR 类型变量。
如前面示例所示,Tutorial D中的元组选择器调用通常由关键字TUPLE及由大括号封闭的“属性名/表达式” 对逗号列表组成。注意,Tutorial D中的关键字TUPLE具有双重使命——既用于我们见过的元组选择器调用,又用于更早见过的元组类型名称。类似说明也适用于关键字RELATION(参见3.3节“关系是什么”)。
定义的推论
此刻,我要强调一些前述定义的重要推论。
第一个推论:从来就没有元组包含null。这是因为,根据定义,每个元组都对它的每个属性包含一个(某种相应类型的)值,而null不是值(如第1章中所述),尽管SQL经常将null显式地用作null值。建议:因为“null值”(null value)一词作为术语自相矛盾,所以别用它;说“null”就行。注意,这个建议并不是故弄玄虚,它关乎正确的思考。SQL在处理null的方面存在很多错误,其中一些就是因为SQL有时(但也不总是)认为null是值。(事实上,这个矛盾恰恰体现在此概念在SQL标准中的定义:null值是一个特殊的值,用于表明数据值的缺失。换句话说,null是一个表示值不存在的值。)
如果没有任何元组能包含null,那么自然也没有关系可以包含null;因此,我们至少就有一个正式的理由来驳斥“null”的概念。第4章中,我还会给出一些更为实用化的理由。
第二个推论(或一对推论):元组的所有子集都是元组,标题的所有子集都是标题(第1章中提到过,现在要详细说明一下)。举个例子,对于常用的对应供应商S1的元组而言,我们所说的元组中“{SNO,CITY}取值”本身就是另一个(度为2的)元组:
image

它的标题如上图所示,其类型为TUPLE {SNO CHAR,CITY CHAR }。同样,下面也是一个元组:
image

该元组的度为1,类型为 {SNO CHAR }。
我想你肯定知道空集(empty set)——没有元素的集合——是任何集合的子集。所以,空标题是有效的标题!并且,分量集合为空集的元组也是有效的元组(在纸上画出这样元组的图示有些困难,我甚至都不会去尝试)。一个标题为空的元组的类型为TUPLE{};实际上,我们有时将其称为0-元组(0-tuple)以便强调其没有任何分量并且度为0。我们有时也把它叫作空元组(empty tuple)。你可能认为这样的元组在实践中没什么用;但是,它却是十分重要。这可能让你大吃一惊。3.7节“TABLE_DUM和TABLE_DEE”会对此进行详细说明。
现在先回到原先的供应商S1元组(度为4)。假设我们得到了这个元组并想从中得到一些属性(比如SNO属性)的实际值,那么我们就必须从包含它的元组中提取(extract)值。Tutorial D使用SNO FROM t语法形式达到此目的(其中,t可以是任何表达式,只要该表达式具有SNO属性的元组即可)。SQL使用点限定(dot qualification):t.SNO。
注意:从上文可知,一个值和一个包含值的元组不是一回事;尤其是当它们的类型不同时。此逻辑区分类似于第2章中“元组”和“包含元组的关系”之间的区别,它们也不是一回事(它们的类型也不相同)。
回到元组相等性(tuple equality)的概念(第1章中提过,现在要详细说明)。第2章中说过,“=”比较运算符是(实际上必须是)针对所有类型定义的,元组类型当然也不能例外。基本上,当且仅当两个元组是完全一样的元组时,这两个元组才是相等的(就好像两个整数是相等的,当且仅当它们是完全一样的整数时)。但是,仔细研读元组相等性的语义还是很有必要的,因为关系模型中依赖此概念的内容实在是太多了。比如,候选键、外键以及几乎所有的关系代数运算符都是依赖它进行定义的。下面是元组相等性的精确定义:
定义 元组t和t'是相等(equal)的,当且仅当它们具有相同的属性A1,A2,…, An(换言之,它们类型相同)并且,对于所有的i(i=1,2,…,n),t中Ai的值v与t'中Ai的值v'相等。
另外,两个元组是互为重复(duplicate)的,当且仅当它们是相等的(这第1章中说过,虽然显而易见但还是要说一下)。因此,图1.3中suppliers关系的供应商S1元组与它自己相等。所以,它对于它自己是重复的;而它与其他任何东西都不相等,不与其他任何东西(具体的说,就是其他元组)重复。
此外,上述定义的一个直接推论就是所有的0-元组都互为重复。因此,我们决定:如果要说术语就用0-元组(the 0-tuple)代替“一个”0-元组("a" 0-tuple)。实际上,我们一直都是这么做的。另外,我们可以说0-元组是任何元组的子集(就好像我们可以说空集是任何集合的子集一样)。
所以,比较运算符“=”和“≠”都很有必要适用于元组。然而,运算符“<”和“>”却不适用。原因在于,元组是基本集合(具体而言是分量集合),而“<”和“>”这样的运算符对于集合是无意义的。
在本节结束前,请读者注意一下本章结尾部分的练习3.16(在附录F中对此练习也有讨论),我强烈建议你在上面花些时间。本书后续章节会关注由此练习引申出的一些要点。

相关实践学习
体验RDS通用云盘核心能力
本次实验任务是创建一个云数据库RDS MySQL(通用云盘),并通过云服务器ECS对RDS MySQL实例进行压测,体验IO加速和IO突发带来的性能提升;并通过DMS执行DDL,将数据归档到OSS,再结合云盘缩容,体验数据归档带来的成本优势。
相关文章
|
2月前
|
SQL 关系型数据库 MySQL
创建SQL数据库的基本步骤与代码指南
在信息时代,数据管理显得尤为重要,其中数据库系统已成为信息技术架构的关键部分。而当我们谈论数据库系统时,SQL(结构化查询语言)无疑是其中最核心的工具之一。本文将详细介绍如何使用SQL创建数据库,包括编写相应的代码和必要的步骤。由于篇幅限制,本文可能无法达到您要求的2000字长度,但会尽量涵盖创建数
59 3
|
2月前
|
SQL 监控 关系型数据库
SQL错误代码1303解析与处理方法
在SQL编程和数据库管理中,遇到错误代码是常有的事,其中错误代码1303在不同数据库系统中可能代表不同的含义
|
2月前
|
SQL 安全 关系型数据库
SQL错误代码1303解析与解决方案:深入理解并应对权限问题
在数据库管理和开发过程中,遇到错误代码是常见的事情,每个错误代码都代表着一种特定的问题
|
4月前
|
存储 SQL 安全
【数据库高手的秘密武器:深度解析SQL视图与存储过程的魅力——封装复杂逻辑,实现代码高复用性的终极指南】
【8月更文挑战第31天】本文通过具体代码示例介绍 SQL 视图与存储过程的创建及应用优势。视图作为虚拟表,可简化复杂查询并提升代码可维护性;存储过程则预编译 SQL 语句,支持复杂逻辑与事务处理,增强代码复用性和安全性。通过创建视图 `high_earners` 和存储过程 `get_employee_details` 及 `update_salary` 的实例,展示了二者在实际项目中的强大功能。
43 1
|
3月前
|
SQL 安全 数据库
基于SQL Server事务日志的数据库恢复技术及实战代码详解
基于事务日志的数据库恢复技术是SQL Server中一个非常强大的功能,它能够帮助数据库管理员在数据丢失或损坏的情况下,有效地恢复数据。通过定期备份数据库和事务日志,并在需要时按照正确的步骤恢复,可以最大限度地减少数据丢失的风险。需要注意的是,恢复数据是一个需要谨慎操作的过程,建议在执行恢复操作之前,详细了解相关的操作步骤和注意事项,以确保数据的安全和完整。
129 0
|
4月前
|
JSON 数据格式 Java
化繁为简的魔法:Struts 2 与 JSON 联手打造超流畅数据交换体验,让应用飞起来!
【8月更文挑战第31天】在现代 Web 开发中,JSON 成为数据交换的主流格式,以其轻量、易读和易解析的特点受到青睐。Struts 2 内置对 JSON 的支持,结合 Jackson 库可便捷实现数据传输。本文通过具体示例展示了如何在 Struts 2 中进行 JSON 数据的序列化与反序列化,并结合 AJAX 技术提升 Web 应用的响应速度和用户体验。
119 0
|
4月前
|
SQL 数据库 开发者
|
4月前
|
SQL 数据库 索引
SQL 编程最佳实践简直太牛啦!带你编写高效又可维护的 SQL 代码,轻松应对数据库挑战!
【8月更文挑战第31天】在SQL编程中,高效与可维护的代码至关重要,不仅能提升数据库性能,还降低维护成本。本文通过案例分析探讨SQL最佳实践:避免全表扫描,利用索引加速查询;合理使用JOIN,避免性能问题;避免使用`SELECT *`,减少不必要的数据传输;使用`COMMIT`和`ROLLBACK`确保事务一致性;添加注释提高代码可读性。遵循这些实践,不仅提升性能,还便于后期维护和扩展。应根据具体情况选择合适方法并持续优化SQL代码。
56 0
|
4月前
|
SQL Java 数据库连接
【Azure 应用服务】Java ODBC代码中,启用 Managed Identity 登录 SQL Server 报错 Managed Identity authentication is not available
【Azure 应用服务】Java ODBC代码中,启用 Managed Identity 登录 SQL Server 报错 Managed Identity authentication is not available
|
4月前
|
SQL DataWorks 大数据
DataWorks操作报错合集之SQL代码行数过长产生报错,该如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。