【数据库系统原理】第4篇:关系数据结构的形式化定义:域、笛卡尔积与关系模式
目录
一、域:关系的原子材料
二、笛卡尔积与关系:从全组合到有意义的事实
三、关系模式与关系实例:结构的恒常与内容的流变
四、码:不可再少的身份标识
五、外码与参照完整性:关系之间的逻辑契约
六、形式化的价值:从规则到保证
一、域:关系的原子材料
在关系模型中,一切结构的起点是一个看似简单却极易被忽视的概念——域。
域(Domain)的形式化定义是:一组具有相同数据类型和语义的原子值的集合。这一定义包含三重约束。其一,域中的值必须是原子的——从关系模型的理论视角看,它不可再分。这并非物理意义上的不可拆分(所有数据在物理上最终都是比特),而是逻辑意义上的不可拆分:关系模型不再关心域内值的内部结构,域值被视为操作的基本单元。其二,域中的值具有共同的数据类型,如整数、字符串、日期等。其三,域中的值共享某种语义,这种语义规定了这些值在现实世界中代表什么——例如,域“年龄”不仅是0到150之间的整数,更重要的是,这个整数表示的是“一个人存活的年数”而非别的任何意义。
域与编程语言中“类型”的概念有相似之处,但域的内涵更为丰富。一个类型通常只限定值的表示范围(如32位有符号整数的取值范围),而域在此基础上还附加了业务语义约束。例如,域“课程编号”和域“学生人数”在物理上都可能是整数类型,但一个合法的课程编号(如C001的某种数值编码)未必是一个合法的学生人数(它不可能为负,也不太可能超过一个合理的上限)。数据库管理系统在执行比较、连接等操作时,通常是基于域来进行类型相容性判定的——两个值只有来自同一个域(或域之间定义了相容关系),比较才有逻辑意义。
为域赋予一个语义名称并将其置于关系的某个位置上,这个带有角色的域便成为属性。从形式化的角度,属性是从关系模式到域的映射:给定关系模式R,其属性A是R上的一个函数,该函数将关系模式中的每一列映射到一个特定的域。正是这种映射关系,保证了每一列数据的取值都受到域的严格约束。
二、笛卡尔积与关系:从全组合到有意义的事实
有了域的严格定义,笛卡尔积和关系的形式化定义便可以精确展开。
设有n个域D₁, D₂, ..., Dₙ(它们可以相同也可以不同),这些域的笛卡尔积记作D₁ × D₂ × ... × Dₙ,定义为所有n元有序组(d₁, d₂, ..., dₙ)的集合,其中dᵢ ∈ Dᵢ(即第i个分量取自第i个域)。用集合论的记法:
D₁ × D₂ × ... × Dₙ = { (d₁, d₂, ..., dₙ) | dᵢ ∈ Dᵢ, i = 1, 2, ..., n }
每一个这样的n元有序组被称为一个元组。笛卡尔积的基数(元素个数)等于各域基数的乘积:|D₁| × |D₂| × ... × |Dₙ|。当n和域基数增大时,笛卡尔积的规模呈指数级膨胀——这种组合爆炸是后续讨论查询优化时反复出现的话题。
笛卡尔积本身是一个数学构造,它包含了所有可能的组合,不管这些组合在现实世界中是否有意义。关系正是从这些可能的组合中筛选出那些在业务上真实成立的组合。其形式化定义为:
给定一组域D₁, D₂, ..., Dₙ,这组域上的一个关系(Relation)r是笛卡尔积D₁ × D₂ × ... × Dₙ的任意一个有限子集。记作r ⊆ D₁ × D₂ × ... × Dₙ。
这个定义的两个限定词值得强调。其一,关系是子集——它不必包含笛卡尔积的全部元组。事实上,在实际业务中,关系包含的元组数通常远小于笛卡尔积的规模。子集关系精确定义了“关系表达了域之间某种有意义的关联”这一直觉——只有那些在现实世界中成立的关联才会被纳入子集。其二,关系是有限子集——尽管理论上笛卡尔积可能是无限的,但实际数据库中存储的关系实例始终是有限的。这一限定将关系模型牢牢锚定在可实现的计算范畴之内。
设关系r包含m个元组,每个元组包含n个分量(对应n个属性),我们称r是一个m行n列的关系。行的顺序无关紧要——因为关系是集合,集合的元素间没有顺序;列的顺序在理论层面也无关紧要,因为列通过属性名而非物理位置来标识。这两个“无关紧要”在工程实践中并非总能完全兑现(物理存储总是有序的),但它们是衡量一个数据库系统“关系纯度”的理论标尺。
三、关系模式与关系实例:结构的恒常与内容的流变
初学者极易混淆的一对概念,是关系模式与关系实例。这一区分类似于编程语言中“类型”与“变量值”之间的区分——类型定义了结构,变量值是该结构在某一时刻的具体填充。
关系模式(Relation Schema)是对一个关系结构的描述。它可以形式化地记作R(A₁:D₁, A₂:D₂, ..., Aₙ:Dₙ),其中R是关系的名称,Aᵢ是属性名,Dᵢ是属性Aᵢ所基于的域。关系模式是相对稳定的——一旦设计完成,一个关系模式通常会保持很长一段时间不发生结构性变化。所有符合该模式的数据都将遵循相同的结构约束。
关系实例(Relation Instance)则是关系模式在某一特定时刻的具体内容——即当前实际存储在数据库中的元组集合。关系实例是动态的,随着插入、删除、更新操作的发生而不断变化。一个关系模式在任何时刻都有且仅有一个关系实例(可能为空),而同一关系模式在时间轴上对应于一个不断演化的实例序列。
这一区分之所以关键,是因为后续讨论的所有完整性约束(域约束、实体完整性、参照完整性)都是施加在关系模式上的永久性规则,而数据库系统运行时的具体工作则是确保每一个关系实例都满足这些规则。当用户插入一条数据、更新一个字段时,系统本质上是在执行一次“从当前合法实例到另一个合法实例”的状态跃迁检查——任何试图生成非法实例的操作都将被拒绝。
将关系的数学定义与关系模式/实例的区分结合起来,我们可以得到如下精确表述:设关系模式为R(A₁:D₁, A₂:D₂, ..., Aₙ:Dₙ),则R的一个合法关系实例r满足r ⊆ D₁ × D₂ × ... × Dₙ,且r是有限集合。数据库(Database)则是多个关系实例的集合,而数据库模式(Database Schema)是多个关系模式的集合,外加模式间约束的集合。
四、码:不可再少的身份标识
在关系实例包含的所有元组中,如何唯一地标识某一行,是实现数据定位、关联和更新的基本前提。关系模型使用“码”这一概念来承担此责。
超码(Superkey)是关系模式中一个属性或一组属性的集合,其取值足以唯一标识关系中的每一个元组。形式化地:设K是关系模式R的属性子集,若对于R的任意合法实例r,r中不存在两个不同的元组在K的各个属性上取值完全相同,则K是R的一个超码。超码的定义保证了在属性集K上的取值组合具有全局唯一性。
超码的问题在于它可能包含冗余。如果K已经是超码,那么任何包含K的属性集也必然是超码——因为增加属性不会破坏唯一性。例如,在“学生”关系中,{学号}是超码,那么{学号, 姓名}、{学号, 姓名, 出生日期}也都是超码,但后面这些超码携带了不必要的额外属性。
候选码(Candidate Key)是“最小”的超码——它是一个超码,且其任意真子集都不再是超码。换言之,候选码中的每一个属性都是维持唯一性所不可或缺的,去掉任何一个,唯一性就不再成立。一个关系模式可以同时存在多个候选码。例如,在“学生”关系中,如果“学号”和“身份证号”各自都能唯一标识学生,且“学号”不需要借助身份证号来维持唯一性,反之亦然,那么{学号}和{身份证号}都是候选码。
主码(Primary Key)是设计者从候选码中人为选定的一个,作为关系实例中元组的首要标识方式。未被选中的候选码则称为替代码(Alternate Key)。主码的选择通常是出于工程考虑而非理论必需——优先选择属性个数少、长度短、取值稳定且不易变更的候选码作为主码。主码的选定意味着设计者承诺:该关系的每一个合法实例中,主码属性的取值绝不为空,且绝不重复。
上述对于主码取值不为空的承诺,被形式化为实体完整性规则:在任何关系实例中,主码的任何属性都不得取空值(NULL)。这一规则的合理性源于对实体可标识性的基本要求——如果主码为空或部分为空,对应的元组就无法被可靠地标识与引用,它作为一个“独立实体”的存在根基就被动摇了。实体完整性是关系模型中最基本、最不可动摇的约束之一。
五、外码与参照完整性:关系之间的逻辑契约
单个关系内部的完整性由域约束和实体完整性来保障。但一个数据库通常包含多个关系,这些关系之间存在着千丝万缕的语义关联——学生隶属于某个院系,订单属于某个顾客,选课记录引用了学生和课程。这些跨关系的关联,必须同样受到严格的逻辑约束。承担这一使命的机制,就是外码与参照完整性规则。
外码(Foreign Key)的形式化定义涉及两个关系模式。设R₁和R₂是两个关系模式(它们可以是同一个模式——自引用场景),设FK是R₁的一个属性或属性组。如果满足以下两个条件,则称FK是R₁的一个外码,它参照(Reference)了R₂:
其一,FK中的属性与R₂的主码属性必须基于相同的域。这一要求保证了外码取值与被参照目标在数据类型和语义上的可比性。
其二,在任意合法的数据库实例中,R₁中任意元组在FK上的取值,要么全部为空(每个属性均为NULL),要么与R₂中某个元组在主码上的取值完全匹配。换言之,R₁在FK上的每一个非空值,都必须在R₂的主码中找到一个“指涉对象”。
这第二个条件,便是参照完整性规则(Referential Integrity Rule)——外码取值要么为空,要么等于被参照关系中某个主码值。空值在此处的语义是“该元组在这一关联上尚未建立指涉”,例如一个暂未分配导师的研究生,其“导师工号”外码可以暂时为空。但一旦它被赋予了一个非空值,这个值就必须对应一位真实存在的教师。
外码定义的深刻之处在于,它建立了一种跨越关系边界的逻辑约束。它不是物理指针,不携带任何存储地址信息,不要求连接算法是什么,不关心索引结构。它只声明一条铁律:在A表中声称与B表有关联的任何记录,都必须能在B表中找到被关联的那个对象。这条铁律是关系数据库中跨表数据一致性的最后一道防线——数据库管理系统通过强制执行参照完整性,确保整个关系网络不会出现“孤儿记录”:一个订单不可能属于一个不存在的顾客,一条选课记录不可能引用一门已被删除的课程。
六、形式化的价值:从规则到保证
行文至此,我们完成了对关系数据结构最核心概念的形式化构建。这些概念——域、笛卡尔积、关系、关系模式与实例、超码与候选码、主码、外码——共同构成了关系模型的骨架。它们不是各自孤立的知识点,而是一个逐级推导、环环相扣的定义体系:域定义了取值的原子范围,笛卡尔积定义了域之间的全组合,关系从全组合中筛选出有意义的事实,关系模式固定了这种筛选的框架,码确保了框架内每一行的可标识性,外码则跨越框架建立了逻辑契约。
这一整套形式化体系之所以重要,是因为它将数据库管理从经验技艺提升为可证明的工程科学。实体完整性、参照完整性、域完整性——这三大完整性约束分别守护着数据在行内、行间和跨表三个维度的逻辑自洽。当数据库系统在每一次数据修改操作时强制执行这些约束,它就为上层应用提供了强有力的担保:无论程序逻辑多么复杂,无论并发操作如何交叠,数据的基本逻辑结构不会腐坏。
下一篇,我们将在这套形式化基石之上,系统展开三大完整性的完整论述——它们如何具体地保护数据库免于逻辑污染,以及它们在实际工程场景中的实施策略与取舍。
