T-SQL基础教程:关系模型
作者:Itzik Ben-Gan
图书:http://item.jd.com/11362891.html
关系模型是基于集合理论和谓词逻辑进行数据管理和操作的语义模型。如上所述,它是由Edgar F. Codd博士创建的,后来由Chris Date、Hugh Darwen等阐释和发展。关系模型的第一个版本是于1969年由Codd在IBM研究报告“Derivability, Redundancy, and Consistency of Relations Stored inLarge Data Banks(大型数据库中关系模型存储的可导、冗余和一致性)”中提出的,修订版本是由Codd于1970年在一篇名为“A Relational Model of Datafor Large Shared Data Banks(大型共享数据库的数据关系模型)”的文章中提出的,发表在《美国计算机学会通讯》杂志上。
关系模型的目标是确保数据的一致性表示,最小化或是没有冗余且不牺牲完整性,并将定义数据的完整性(强制数据一致性)作为模型的一部分。RDBMS应假定实施关系模型并提供方法来存储、管理、实施完整性和查询数据。关系模型基于强壮的数学基础的事实,意味着提供了一个可靠的数据模型实例(在后面将建立一个物理数据库)。可以肯定地说,当某个设计存在缺陷时不应当是靠直觉。
关系模型涉及命题、谓词、关系,元组和属性等概念。对于非数学家,这些概念可能非常吓人。下面几节将以一种通俗的、非数学的方式讨论模型中的一些关键方面,并解释它们如何与数据库进行关联。
1.命题、谓词和关系
普遍认为“关系”术语源于表之间的关系,这是不正确的。“关系”实际上是数学术语的关系。在集合理论中,关系是集合的表现形式。在关系模型中,关系是相关的信息的集合,与SQL中相对应的就是一个表——尽管不能完全对应。关系模型中的一个关键点是,单个的关系应代表一个单个集合(如客户)。值得注意的是,对多个关系操作(基于关系代数)的结果会是一个关系(例如,两个关系之间的联接)。
注意:关系模型分为关系和关系变量,但为了让事情简单,我不想引入这种区分;相反,我会使用两种情况阐述关系。此外,关系是由表头和主体组成。表头包含一组属性(SQL中称之为列),其中每个元素由一个属性名称和类型名称标识。主体包含一个元组(SQL中称之为行)集合,其中每个元素都由键标识。为了让事情简单,我会将表称之为行集。
当为数据库设计数据模型时,要使用关系(表)来表示所有数据。你首先要确定需要在数据库中表示的命题。命题应当是一个断言或必须为“真”或“假”的语句。例如,语句“雇员Itzik Ben- Gan出生于1971年2月12日,在IT部门工作”是一个命题,如果这是一个真命题,它将表现为Employees(雇员)表中的一个行,如果是假命题则根本不会出现。这个假设被称为“封闭世界假设”(close world assumption,CWA)。
下一步是将命题形式化。为此,你要取出实际数据(关系的主体)并定义结构(关系的表头)——例如,创建命题的谓词。你可以以参数化命题方式思考谓词,关系的表头包含一个属性集合。注意术语“集合”的使用,在关系模型中属性是无序且互异的。属性由属性名称和类型名称进行标识,例如,一个Employees(雇员)关系的表头可能包含下列属性(属性名称和类型名称以成对方式出现):employeeid 整型、firstname 字符串型、lastname字符串型、birthdate 日期型、departmentid整型。
类型是关系最基本的构造块,它约束了属性是一个可能或有效值的确定集合。例如,INT类型是范围自–2,147,483,648至2,147,483,647所有整数的集合。类型是数据库中谓词的最简单形式之一,因为它限制了该属性的允许值。例如,数据库不会接受一个雇员的出生日期为1971年2月31日的命题(更不用提像“abc”这样的生日)。 注意,类型不受像整型或字符串型等基本类型的限制,它也可以是可能值的枚举,例如枚举可能的工作岗位。类型是非常复杂的,或许最好方法将类型看作是一个类——封装了支持它的数据和属性。一个复杂类型的示例是:一个支持多边形的几何形状类型。
2.缺失值
关系模型的一个方面是对于“是否谓词应限制于二值逻辑”的激情辩论。也就是说,在二值谓词逻辑中谓词是“真”或“假”。如果谓词不是“真”,那肯定是“假”。二值谓词逻辑的使用遵循了一个名为“排中律”的数学定律。不过,也有人说具有三值(甚至四值)谓词逻辑空间,思考一下像缺失值的账号情况。一个谓词,涉及到缺失值则导致既不是“真”也不是“假”——它是未知的。 例如,一个Employees(雇员)关系的手机属性,假设某些雇员的手机号码丢失了,你怎么把这一事实表示数据库中?这要使用三值逻辑实现,手机属性应当允许有一个代表缺失值的特定标记。然后,这种缺失值情况下,将该手机属性与一些指定数字比较,谓词也将产生未知。三值谓词逻辑是指来自谓词结果的三种可能逻辑值──“真”、“假”和“未知”(true、false和unknown)。
有些人认为三值谓词逻辑是非关系的,而有些人认为这是关系。Codd实际上主张四值谓词逻辑,提出缺失值有两种不同情况:缺失但可用(A-Mark)和缺失但不可用(I-Mark)。例如,“缺失但可用”是雇员拥有手机,但是你不知道是什么号码;“缺失但不可用”是雇员根本就没有手机。根据Codd的主张,应当有两个特定标记来支持这两种缺失值情况。SQL通过支持NULL标记实现了三值谓词逻辑,以表示缺失值的通用概念。SQL中对NULL和三值谓词逻辑的支持是造成极大混乱和复杂性的根源,尽管人们认为缺少的值是现实的一部分。此外,另一个选择是仅使用二值谓词逻辑,这是不会造成问题的。
3.约束
关系模型的最大好处是能够把定义数据的完整性作为模型的一部分。数据完整性通过在数据模型中定义的约束规则实现,并由RDBMS实施。实施完整性的最简单方式是指定属性类型的nullability(是否支持或不支持NULL标记)标志。约束也可以通过模型自身实施,例如,关系Orders(orderid, orderdate, duedate,shipdate) 中每笔订单有3个互异日期,而关系Employees(empid) 与EmployeeChildren(empid,childname)允许每个雇员有0至可数的无穷个子级。
约束的其他例子还包括提供实体完整性的候选键和提供引用完整性的外键。候选键是定义了一个或多个属性的键,防止关系中出现多个相同的元组(SQL中的行),基于候选键的谓词可以唯一地标识行(如雇员)。你可以在关系中定义多个候选键,例如,在Employees关系中,可以在employeeid、SSN(社会安全号码)等属性上定义候选键。通常,你可以任意选择一个候选键作为主键(例如,Employees关系中的employeeid),并作为标识行的首选方式。所有其他候选键称为备用键。
外键用于强制引用完整性。外键定义了关系的一个或多个属性(称为引用关系)引用另一个关系(或同一关系)的候选键,此约束限定了引用关系的外键属性中的值,应是出现在被引用关系(父表)的候选键属性中的值。例如,假设Employees关系具有一个定义在departmentid属性上的外键,它引用Departments关系中的主键属性departmentid,这意味着Employees.departmentid中的值仅限于出现在Departments.departmentid中的值。
4.规范化
关系模型还定义了规范化规则(也称为范式)。规范化是一个常规的数学过程,用于确保每个实体都由单一关系表示。在规范化的数据库中,要在数据修改过程中避免异常,并不牺牲完整性的情况下保持最低限度冗余。如果按照实体关系模型(Entity Relationship Modeling,ERM)来表示每个实体及其属性,你可能不需要规范化;相反,你应使用规范化来巩固和确保模型是正确的。以下各节简要将介绍一下由Codd提出的前三个范式(1NF、2NF和3NF)。
(1)1NF
第一范式是说关系(表)中的元组(行)必须是唯一的,并且属性是原子化的。这是一个关系的冗长定义,换句话说,如果表正确地表示了关系,它已经符合了第一范式。
通过为表定义一个唯一键就可以实现唯一行。
你仅能执行属性类型所定义部分的操作,属性的原子性是主观的,这与集合的定义是主观的一样。例如,Employees关系中雇员姓名应当使用一个(fullname)、两个(firstname和lastname)还是三个(firstname、middlename和lastname)属性表示呢?答案取决于应用程序。如果应用程序需要分别处理雇员的姓名部分(如处于搜索目的),则有必要把它们分开,否则,则不需要。
同样的,基于应用程序需求,属性可能不被完全原子化,也有可能被亚原子化。例如,如果地址属性被作为一个特定应用程序的原子,不将“城市”作为地址的一部分会违反第一范式。
这个范式经常被误解,有人认为试图模仿数组会违反第一范式。例如,定义的YearlySales关系具有以下属性:salesperson、qty2010、qty2011和qty2012。但在本示例中,你不会真的违反第一范式,你只需施加一个约束──将数据限制为特定的三年:2010、2011和2012。
(2)2NF
第二范式涉及两个规则。一个规则是数据必须满足第一范式,另一个规则提及非键属性和候选键属性之间的关系。对于每个候选键,每个非键属性必须是对整个候选键的完全函数依赖。换言之,非键属性不能是对候选键某部分的完全函数依赖。更加口语化的,如果你要获取任何非键属性值,你需要提供相同元组中候选键的所有属性的值;如果你知道候选键的所有属性的值,你就可以检索到任何元组的任何属性的任何值。
下面是一个违反第二范式的例子,假设你定义了一个名为Orders的关系,表示订单和订单行的信息,如图1-1所示。Orders关系包含下列属性:orderid、productid、 orderdate、qty、customerid和companyname。主键定义为orderid和productid。
图1-1 符合2NF之前的数据模型
图1-1中违反了第二范式,因为有非键属性仅依赖于候选键(即该示例的主键)的一部分。例如,你可以仅通过orderid找到订单的orderdate,以及customerid和companyname。要符合第二范式,你需要将原来的关系拆分为两个关系:Orders和OrderDetails,如图1-2所示。Orders关系将包括orderid、orderdate、customerid和companyname属性,主键定义为orderid。OrderDetails关系将包括orderid、productid和qty,主键定义为orderid和productid。
图1-2 3NF之前符合2NF的数据模型
(3)3NF
第三范式也有两个规则。数据必须满足第二范式,同时,所有非键属性必须依赖于非传递的候选键。通俗的讲,该规则的意思是所有非键属性必须相互独立。换句话说,一个非键属性不能依赖于另一个非键属性。
先前所述的Orders和OrderDetails关系现在已经符合第二范式。请记住,此时的Orders关系包含orderid、orderdate、customerid和companyname属性,主键定义为orderid。customerid和companyname均依赖于整个主键──orderid。例如,你需要整个主键来查找代表订单中客户的customerid,同样,你需要整个主键查找订单中客户的公司名称。然而,customerid和companyname也是互相依靠的。为满足第三范式,你需要添加包含customerid(作为主键)和companyname的Customers关系,如图1-3所示,然后你就可以从Orders关系中删除companyname属性。
图1-3 符合3NF后的数据模型
通俗的讲,2NF和3NF通常以这句话概括:“每个非键属性依赖于键,依赖于整个键,并且除了键别无他物──请Codd帮助作证此话”。
还有比Codd首创的前三个范式更高的范式,涉及复杂的主键和瞬时数据库,但这些超出了本书的范围。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。