ODL
数据模型的组成和抽象过程
数据模型的组成要素
- 数据模型
- 是描述客观事物特征的模型,包括事物本身的特性和事物之间的联系
- 数据模型通常由数据结构、数据操作和数据的约束条件三个要素组成
- 数据结构
- 数据结构用于描述系统的静态特性
- 数据结构是所研究的对象的特性的集合,它是刻画一个数据模型性质最重要的方面
- 数据结构有层次结构、网状结构、关系结构和面向对象的数据结构四种类型,按照这四种结构命名的数据模型分别称为层次模型、网状模型、关系模型和面向对象模型
- 数据操作
- 数据操作用于描述系统的动态特性。数据操作是对数据库中各种数据操作的集合,包括操作及相应的操作规则
- 数据模型必须定义操作的确切含义、操作规则以及实现操作的语言
- 数据的约束条件
- 数据的约束条件是一组完整性规则的集合
- 完整性规则是给定的数据模型中,数据及其联系所具有的制约和依存规则,用以限定符合数据模型的数据库中的数据, 以保证数据的正确、有效、相容和一致性
- 数据模型应提供定义完整性约束条件的机制,反映在具体应用中,就是所涉及的数据必须遵守的特定的语义约束条件
数据的抽象数据的抽象
- 由于计算机不能直接处理现实世界中的具体事物,所以人们必须将具体事物转换成计算机能够处理的数据
- 在数据库中,用数据模型来抽象、表示和处理现实世界中的数据
- 数据库即是模拟现实世界中某应用环境(一个企业、单位或部门)所涉及的数据的集合,它不仅要反映数据本身的内容,而且要反映数据之间的联系
- 为了把现实世界中的具体事物抽象、组织为某一DBMS支持的数据模型,在实际的数据处理过程中
- 首先将现实世界的事物及联系抽象成信息世界的信息模型
- 然后再抽象成计算机世界的数据模型
- 信息模型并不依赖于具体的计算机系统,不是某一个DBMS所支持的数据模型,它是计算机内部数据的抽象表示,是概念模型
- 概念模型经过抽象,转换成计算机上某一DBMS支持的数 据模型。所以说,数据模型是现实世界的两级抽象的结果
- 在数据处理中,数据加工经历了现实世界、信息世界和计算机世界三个不同的世界,经历了两级抽象和转换。这一过程如图所示
对象定义语言
ODL中的类
- ODL(Object Definition Language,对象定义语言),是用面向对象的术语说明数据库中数据的结构的一种标准语言
- ODL的主要用途是书写面向对象数据库的设计,进而将其直接转换成面向对象数据库管理系统(OODBMS)中的数据结构
- 在面向对象的设计中,把准备建立数据库模型的世界看作由对象组成,而对象是某种可观察的实体。假定对象有唯一的对象标识(OID,Object IDentity),各个不同的对象之间通过对象标识来区别
interface Movie{ //Movie类的ODL说明
attribute string title;
attribute integer year;
attribute integer length;
attribute enum Film
{color,blackAndwhite} filmType;
}
- ODL中以类作为一个信息单元,类似于E/R图中的实体集, 也就是关系模型中的关系(表)
- 为了组织信息,将具有相似特性的对象归为一类。相似特性是指:
- 属于同一类的对象所表示的现实世界在概念上应该是类似的。也就是说,属于同一类的对象在现实世界中应属于同一概念
- 属于一类的对象其特性必须相同,即具有相同的属性
- 在ODL中,形式最简单的类的说明应包括:
- 关键字interface 表示类说明的开始
- 类的名字 表示某种具有共同特性的对象的集合的变量
- 用花括号括起来的类的特性表(包括属性和联系)
interface 类的名字 {
<特性表>;
}
- 在不同的类中,属性的定义可以用相同名称,但却具有不同的类型
interface Movie{ //Movie类的ODL说明
attribute string title;
attribute integer year;
attribute integer length;
attribute enum Film
{color,blackAndwhite} filmType;
}
ODL中的数据类型
在ODL中,属性和联系的说明需要提供数据类型,ODL中数据类型包括基本类型、聚集类型和结构。
基本类型
基本类型包括两大类:
- 原子类型:整型int、浮点型float、字符char、字符串string、布尔型bool和枚举型enum
- 布尔型的取值是“真”或“假”
- 枚举型是名字的列表,它和整型是同义词
- 在类Movie的说明中就有一个枚举型的属性filmType,效果上就是把名字color和blackAndwhite定义成整数0和1的同义词
- 接口类型:即定义好的某个类
- 例如定义了类Movie后,Movie就代表了一个接口类型。我们把类也看作是基本类型
聚集类型
聚集类型:指通过以下四种类型构造符将基本类型组合而成的新的数据类型。(假设T是任意一种基本类型):
- 集合
- Set
<T>
表示由类型为T的元素构成的集合。元素无序、不重复
- Set
- 包
- Bag
<T>
表示由类型为T的元素构成的包或多重集。元素无序、可重复
- Bag
- 列表
- List
<T>
表示类型为T的元素构成的有序列表。元素有序、可重复。string类型可以看作是List<char>
类型的简化形式 - 例 {1,2,1}和{2,1,1}不是集合,是相同的包,不同的列表
- List
- 数组
- 如果i是一个整数,则Array<T,i>表示由i个类型为T的元素组成的数组
- 例 Array<char,10>
结构
如果T1,T2,…,Tn是类型,F1,F2,…,Fn是域名,则Struct N {T1 F1,T2 F2,…,Tn Fn}表示名为N的一个结构,是由n个类型分别为T1,T2,…,Tn的元素构成的,第i个域名是Fi,类型是Ti。Struct也是一种类型构造符
ODL中的数据类型规则
- 属性的数据类型
- 原子类型
- 类型构造符单次应用于原子类型或结构所构成的聚集类型或结构
- 不能是接口类型
- 联系的数据类型
- 接口类型
- 类型构造符单次应用于接口类型所构成的聚集类型
- 不能是原子类型
- 不能是结构
- 联系和属性的数据类型都不能是聚集类型的两次应用
ODL的属性
- 属性:利用某个数据类型的值来描述对象的某个方面的特征。
- 属性说明的四个基本要素:
- 关键字attribute 表示属性说明的开始。
- 属性的数据类型 表示属性的取值空间。
- 属性的名字 表示描述对象某方面特征的变量。
- 分号 ; 表示属性说明的结束。
interface Movie{
attribute string title;
attribute integer year;
attribute integer length;
attribute enum Film
{color,blackAndwhite}filmType;
}
interface Star {
attribute string name;
attribute Struct Addr
{string street,string city} address;
}
- 为某公司设计数据库,要求保存以下信息:雇员:雇员号、姓名、年龄、地址、所在部门。
interface employee{
attribute int employeeID;
attribute string name;
attribute int age;
attribute string address;
attribute string department;
}
联系
联系与反向联系
- 联系与反向联系
联系是描述类的一个对象与同一类或不同类的其他对象之间的关系特性。联系与反向联系总是成对出现的 - 联系与反向联系说明的基本要素包括:
- 关键字 relationship 表示联系说明的开始
- 联系的数据类型 表示该关系特性取值的域
- 联系的名字 表示该关系特性的名字
- 关键字inverse 表示该联系对应的反向联系
- 类名::反向联系的名字 反向联系的名字之前加上类的名字以及两个冒号::表示引用
- 这里的类名与定义该关系特性取值的域中的类名一致
- 分号 ; 表示联系与反向联系说明的结束
interface Movie {
attribute string title;
attribute integer year;
attribute integer length;
attribute enum Film {color,blackAndWhite} filmType;
relationship Set<Star> stars
inverse Star::starredIn;
}
interface Star {
attribute string name;
attribute Struct Addr
{string street,string city} address;
relationship Set<Movie> starredIn
inverse Movie::stars;
}
- 联系的规则:如果类C的联系R把类C的对象x和类D的一个对象或多个对象y1,y2, …, yn的集合相连,那么R的反向联系,即类D中对应的联系,就把类D的每个对象yi和类C的对象x(或还有其他的对象)相连
- 注:联系中C和D也可以同类,即一个联系可以在逻辑上连接自己
自身的联系
设计一个家谱数据库中的类Person,要求:
记录每个人的姓名。
记录血缘关系的联系:母亲、父亲和孩子。对这个数据库用ODL进行描述。
思考:需要几对联系和反向联系?
interface Person {
attribute string name;
relationship Person motherOf
inverse Person::childrenOfFemale;
relationship Person fatherOf
inverse Person::childrenOfMale;
relationship Set<Person> children
inverse Person::parentsOf;
relationship Set<Person> childrenOfFemale
inverse Person::motherOf ;
relationship Set<Person> childrenOfMale
inverse Person::fatherOf ;
relationship Set<Person> parentsOf
inverse Person::children;
}
联系的多重性
- 联系及其反向联系的唯一性要求称为联系的多重性
- 联系的三种类型:
- 从类C到类D的多对多联系 在联系中,至少C中有一个对象和D的对象的集合有关,而在反向联系中,至少D中有一个对象和C的对象的集合有关
- 从类C到类D的多对一联系 在联系中,每个C的对象都和唯一的D的对象有关,而在反向联系中,至少D中有一个对象和C的对象的集合有关
- 从类C到类D的一对一联系 在联系中,每个C的对象都和唯一的D的对象有关,而在反向联系中,每个D的对象都和唯一的C的对象有关
联系的多重性举例
引入类Studio的说明,包含了制片公司与电影之间的联系。
interface Studio{
attribute string name;
attribute string address;
relationship Set<Movie> owns inverse Movie::ownedBy;
}
这样,相应的类Movie也要作相应的改动:
interface Movie{
attribute string title;
attribute integer year;
attribute integer length;
attribute enum Film{color,blackAndwhite} filmType;
relationship Set<Star> stars inverse Star::starredIn;
relationship Studio ownedby inverse Studio::owns;
}
多重性的说明举例
interface Movie{
……
relationship Set<Star> stars
inverse Star::staredIn;
relationship Studio ownedBy
inverse Studio::owns;
}
interface Star{
……
relationship Set<Movie> staredIn
inverse Movie::stars;
}
interface Studio{
……
relationship Set<Movie> owns
inverse Movie::ownedBy;
}
ODL的联系举例
为某公司设计数据库,要求保存以下信息:
- 雇员:雇员号、姓名、年龄、地址、所在部门。
- 部门:名称、雇员、经理、所销售的商品。
- 商品:名称、制造商、价格、型号、编号。
- 制造商:名称、地址、商品名。
interface Employees {
attribute int EmployeesID;
attribute string name; attribute int age;
attribute string address;
relationship Department workIn
inverse Department::myWorker;
relationship Department headOf
inverse Department::header;}
interface Department {
attribute string name;
relationship Set< Employees > myWorker
inverse Employees::workIn;
relationship Employees header
inverse Employees::headOf;
relationship Set<Goods> forSale
inverse Goods::toDep;}
interface Goods {
attribute string name;
attribute float price;
attribute string type;
attribute string number;
relationship Department toDep
inverse Department::forSale;
relationship Set<Manufacturers> madeBy
inverse Manufacturers::producer;}
interface Manufacturers{
attribute string name;
attribute string address;
relationship Set<Goods> producer
inverse Goods ::madeBy;}
联系类型之间的内涵
- 多对一联系是多对多联系的特例,一对一联系是多对一联系的特例
- 多对多的联系R,指联系R有多对多的自由度。随着对象的改变,有时它可能成为多对一的联系甚至一对一的联系
- 同样地,多对一的联系R有时可能成为一对一的联系
ODL中的子类
- 子类和超类
ODL中,如果某一类对象具有另外一类对象所有的特性,同时又有某些其他特性,此时该类为另外一类的子类。另外一类称为该类的超类 - 子类的说明方法:
假设类C是类D的子类,则在类C的说明中,在类名C后面加上冒号和类D的名字。即
interface 子类名:超类名 {
<特性表>;
}
- 子类定义中的特性表中不包含超类中已含有的特性。
- 子类继承其超类的所有特性
ODL中的子类举例
假设要记录卡通片的配音演员。
Cartoon为Movie的子类,用以下的ODL说明:
interface Cartoon:Movie{
relationship Set<Star> voice
inverse Star::voiceof;
}
在Star中增加
relationship Set<Cartoon> voiceof
inverse Cartoon::voice;
子类的多重继承
- ODL的子类具有多重性,其含义包括:
- 一个类可以有多个子类。
- 子类可以有子类,形成类的层次,每个类都继承祖先的特性。
- 一个子类可以有多个超类。
- 说明格式:将这多个超类用逗号隔开放在冒号后。
interface 子类名:超类名1,超类名2,……{
<特性表>;
}
子类的多重继承举例
- Movie的一个子类Cartoon,
interface Cartoon:Movie{relationship Set<Star> voices…;}
- 再假设保存谋杀片信息,
interface Murder:Movie{attribute string Weapon;}
- 有的电影既是卡通片,又是谋杀片,则可以说明另一个子类
Cartoon-Murder来描述这种情况,说明如下:
interface Cartoon-Murder:Cartoon,Murder {}
- 类Cartoon-Murder的特性包含哪些?
包括Movie的所有特性,Cartoon中新增的一个联系,Murder 中新增的一个属性
ODL中的子类举例
用ODL描述军舰数据库。
- 记录每艘军舰的信息,包括名称、排水量、类型。
- 记录下列特殊类型的军舰:
- 炮舰:携带大型火炮的军舰,记录主炮的数量和口径。
- 航空母舰:记录飞行甲板的长度和分派给它们的航空大队的集合。
- 潜艇:记录最大安全深度。
- 攻击型航空母舰:既是炮舰又是航空母舰。
interface Ship { attribute string name;
attribute float displacement;
attribute string type;}
interface Gunship: Ship {
attribute integer numberOfGuns;
attribute float bore;}
interface Carrier: Ship {
attribute float deckLength;
attribute Set<string> airGroups;}
interface Submarine: Ship { attribute float maxSafeDepth;}
interface BattleCarrier: Gunship, Carrier {}
ODL中键码的说明
- ODL中键码的说明要素包括:
- 圆括号
- 关键字key或keys
- 构成键码的属性或属性集列表
- 格式如下:(keys (键码1之属性1,键码1之属性2,…),键码2之属性)
- 如果键码由多个属性组成,则属性表必须用括号括起来
- 键码说明必须紧跟在接口名之后,在左花括号之前说明
- 如果有多个键码,则各个键码之间用逗号隔开
ODL中键码的说明举例
- interface Movie (key (title,year)){//接着为属性和联系表
- (key empID,ssNo)与(key (empID,ssNo))的含义是不同的
- 记录学生信息,并为其选择合适的键码
interface Student(key studentID){
attribute string name;
attribute string studentID;
attribute integer age;
……
}
设计原则
- 真实性
- 数据库的设计应当忠于现实社会
- 避免冗余
- 任何事物只表达一次。冗余会带来危害:
- 占用更多的空间
- 易造成数据不一致
- 任何事物只表达一次。冗余会带来危害:
- 对简单性的考虑
- 避免在设计中引入过多的不必要的元素,以节省空间,避免出错
- 选择合适的元素类型
- 是使用属性还是使用类要根据实际情况确定。一般来说,属性比类或联系更为简单。但是,如果某个事物除名字信息外还有其他信息,就需要使用类