SQL 语言:对象关系数据模型

news/2024/11/9 16:44:49/

文章目录

    • 嵌套关系
    • 复杂类型
    • 继承
    • 引用类型
    • 与复杂类型有关的查询
    • 函数和过程
    • 总结

对象关系数据模型扩展关系数据模型的方式是通过提供一个包括复杂数据类型和面向对象的更丰富的类型系统。

嵌套关系

嵌套关系模型(Nested Relational Model)是关系模型的一个扩展,域可以是原子的也可以赋值为关系。这样元组在一个属性上的取值可以是一个关系,于是关系可以存储在关系中。从而一个复杂对象就可以用嵌套关系的单个元组来表示。如果我们将嵌套关系的一个元组视为一个数据项,在数据项和用户数据库观念上的对象之间就有了一个一一对应的关系。

图书馆示例,每本书存储有书名、作者集合、出版商、关键字集合四种属性。如果这些信息定一个关系,下面的属性将是非原子的:

1)作者。一本书可能有一组作者。

2)关键字。一本书存储了一组关键字,我们希望能够检索出关键字包含该集合中的一个或多个关键字的所有书,这样就将关键字集合域视为非原子的。

3)出版商。与关键字和作者不同,出版社没有一个以集合为值的域。但是,我们可能将出版商视为由名字和分支机构这两个子字段组成的,使得出版商域成为非原子的。

定义一个示例关系 books,该关系是1NF, 如下:

image

假如需要访问单个作者和单个关键字,可以对 books 关系进行拆解,得到 flat-books 关系1NF如下:

image

如果 title→→author、title→→keyword、title→pub-name, pub-branch 是多值依赖,我们可以进一步把这个关系拆解成4NF,使得 flat-books 关系的冗余去除。拆解后关系和示例如下:

                  authors(title, author)keywords(title, keyword)books4(title, pub-name, pub-branch)

image

4NF 设计要求用户她们的查询包含连接操作,因此使得交互复杂化。

面向对象数据库系统支持面向对象数据模型,是一个持久的、可共享的对象库的存储和管理者,而一个对象库是由一个OO模型所定义的对象的集合体。

对象:是由一组数据结构和在这组数据结构上的操作的程序代码封装起来的基本单位。对象之间的界面由 一组消息定义。 一个对象包括属性集合、方法集合和消息集合。

对象标识:是指面向对象数据库中的每个对象都有一个唯一不变的标识。常用的几种标识有值标识、名标识和内标识。

  • 值标识,使用一个值来标识,在关系数据库中通常使用这种形式的标识。例如,一个元组的主码标识了这个元组。
  • 名标识,用用户提供的名称作为标识。这种形式的标识通常用于文件系统中的文件,不管文件的内容是什么,每个文件都被赋予一个名称来唯一标识。
  • 内标识,是建立在数据模型或程序设计语言中内置的一种标识,不需要用户给出标识。面向对象系统中使用这种形式的标识,每个对象在创建时被系统自动赋予一个标识符。

封装:OO模型的一个关键概念就是封装。每一个对象是其状态和行为的封装。封装是对象的外部界面与内部实现之间实行清晰隔离的一种抽象,外部与对象的通信只能通过消息。

:共享同样属性和方法集的所有对象构成了一个对象类(简称类)。例如,学生是一个类,黎明、张军、樊建喜是学生类中的一个对象。类是“型”,对象是“值”。

复杂类型

集合类型

集合是集合体类型(collection type)的一个实例,其他的集合体类型包括数组(array)和多重集合(multiset)(即无序的集合体,其中一个元素可以出现多次)。

SQL-99还提供了新字符型数据大对象数据类型(clob)和二进制数据大对象数据类型(blob)。

sql">create table books(
keyword-set setof(varchar(2))
,author-array varchar (20) array [10]
,book-review clob (10KB) 
,image blob (10MB)
,movie blob (2GB)
);

复杂类型值的创建

在SQL-99中构造器函数(constructor function)用来创建结构类型的值。与结构类型同名的函数就是这个结构类型的构造器函数。

示例20. 给Publisher类型声明一个构造器。

sql">create function Publisher (n varchar(20),b varchar(20))
returns Publisher
beginset name=n;set branch=b;
end

然后我们可以用 Publisher(McGraw-Hill,NewYork) 来创建Publisher 类型的值。

继承

继承可以在类型的级别上进行,也可以在表级别上进行。

类型继承

如希望在数据库中对那些是学生和教师的人分别存储一些额外的信息。

示例31. 假定人的类型定义如下所示,定义学生和教师类型。由于学生和教师是人,所以可以使用继承。

sql">create type Person(
name varchar(20)
,address varchar(20)
);create type Student
under Person
(degree varchar(20),
department varchar(20));create type Teacher
under Person
(salary integer,
department varchar(20))

Student 和Teacher 都继承了Person 的属性,即name和address。Student和Teacher被称为Person 的子类型,Person 是Student 的超类型,同时也是Teacher 的超类型。像属性一样,结构 类型的方法也被它的子类型继承。不过,子类型可以通过在 一个方法声明中使用overriding
method (重载方法)取代原method (方法)的方式重新声明方法,以重定义该方法的作用。

表继承

SQL-99中的子表(subtable)对应的是E-R概念中的特殊化/一般化。子表的类型必须是父表类型的子类型,因此,父表中的每一个属性均出现在子表中

sql">create table people of Person;create table students of Student under people;create table teachers of Teacher under people;

当我们声明students 和teachers 作为people的子表时,每一个students 或teachers 中出现的 元组也隐式存在于peopl e中。如果 一个查询用到people 表,它将查找的不仅仅是直接插入到这 个表中的元组,而且还包含插入到它的子表(也就是students 和teachers)中的元组。

引用类型

面向对象的程序设计语言提供了引用对象的能力,类型的一个属性可以是对一个指定类型的对象的引用。

示例21. 定义一个包括name字段和head字段的Department类型,一个Department类型的表departments。其中,head字段引用到Person类型。方法如下所示

sql">create type Department(
name varchar(20),
head ref(Person) scope people);create table departments of Department;

这里,引用限制在people 表中的元组。在SQL-99中,对一个指向表的元组的引用范围 (scope) 的限制是强制的,它使引用的行为与外码类似。

与复杂类型有关的查询

路径表达式

在SQL-99中对引用取内容使用→符号。

sql"># 查找各部门负责人的名字和地址
select head->name,head->address
from departments;

head->name 带有->符号的表达式被称为路径表达式。由于head是一个对people表中元组的引用,上述查询中的name属性就是people表中元组的name属性。引用可以用来隐藏连接操作,如果没有使用引用要找出一个部门负责人的姓名和地址,我们就需要将departments与people关系显式地做一个连接,因此使用引用可以明显地简化查询。

以集合体为值的属性

一个计算集合体值的表达式可以出现在关系名出现的任何地方。

sql"># books关系模式,查询所有的码中包含“database” 字样的书
select title
from books 
where 'database' in (unnest(keyword-set));

unnest(keyword-set)在无嵌套关系的SQL中相当于一个select-from-where的子表达式。

sql">#  一本特定的书具有三个作者,拆出每个作者
select author-array[1],author-array[2],author-array[3]
from books
where title = 'Database System Concepts';
# 包含形式为“ 书名,作者名” ,对应每本书和书的每个作者
select b.title,a.name
from books as b,unnest(b.author-array) as a;

由于books的author-array属性是一个以集合体值的字段,因此可以用在需要有一个关系存在的from子句中。

嵌套与解除嵌套

将一个嵌套关系转换成具有更少(或没有)的关系为值的属性的形式的过程称为解除嵌套(unnesting)。books关系有author-array和keyword-set两个是集合体的属性;同时books关系另外还有title和publisher两个不是集合体的属性。

sql">select title,A as author,publisher.name as pub-name,publisher.branch as pub-branch,K as keyword
from books as B,unnest(B.author-array) as A,unnest(B.keyword-set) as K;

from 子句中的变量B被声明为以books为取值范围,变量A被声明为以书B的author-array 中的作者为取值范围,同时K 被声明为以书B 的keyword-set 中的关键字为取值范围

函数和过程

SQL 函数和过程

定义一个函数,实现给定一个书名,返回作者数量:

sql">create function author-count(title varchar(20))
returns integer
begin declare a-count integer;select count(author) into a-countfrom authorswhere authors.title = title
return a-count;
end;

以上也可以写成一个存储过程:

sql">create procedure author-count-proc(in title varchar(20),out a-count integer)
begin select count(author) into a-countfrom authorswhere authors.title = title
end;
# 应用
declare a-count integer;
call author-count-proc('Database Systems Concepts',a-count);

外部语言程序

SQL-99允许使用一种程序设计语言(如 C或C++)定义函数。这种方式定义的函数会比 SQL中定义的函数效率更高,无法在SQL中执行的计算可以由这些函数执行。

sql">create procedure author-count-proc(in title varchar(20),out a-count integer)
language C
external name '/usr/avi/bin/author-count-proc';create function author-count(title varchar(20))
returns integer
language C 
external name '/usr/avi/bin/author-count';

过程的构造

1)while 和 repeat 循环语句

一个复合语句有begin … end的形式,在begin和end之间会包含多条SQL语句。语法如下:

sql">declare n integer default 0;
while n<10 doset n=n+1;
end while;repeatset n=n-1;
until n=0
end repeat;

2)for 循环语句

sql">declare n integer default 0;
for r as select balance from account where branc-name='Perryridge'
do set n=n+r.balance
end for

程序在 for 循环开始执行的时候隐式地打开一个游标,并且用它每次获得一个行的值存入 for 循环变量(在上面例子中指r)中。语句leave可用来退出循环,而 iterate 表示跳过剩余语句从循环的开始进入下一个元组。

3)if-then-else 语句与 case 语句

条件语句 if-then-else 语法如下:

sql">if r.balance<1000then set l=l+r.balance
elseif r.balance<5000then set m=m+r.balance
else set h=h+r.balance
end if;

总结

SQL语言和对象关系数据模型的结合,旨在通过提供更加丰富的数据建模能力来满足复杂应用的需求使其能够更好地支持对象特性,如继承、多态以及用户定义类型等。在这种模型中,SQL语言的角色变得尤为重要,因为它不仅需要处理结构化数据,还要能够处理复杂的对象结构。


http://www.ppmy.cn/news/1467101.html

相关文章

DOS编程入门:探索基础、深入技巧与实战应用

DOS编程入门&#xff1a;探索基础、深入技巧与实战应用 DOS编程&#xff0c;作为计算机编程的基石之一&#xff0c;对于初学者来说&#xff0c;既是一种挑战&#xff0c;也是一次深入了解计算机底层运作的绝佳机会。本文将从四个方面、五个方面、六个方面和七个方面&#xff0…

jadx-gui-1.5 反编译工具使用教程 反混淆 Java android 查看签名

JADX&#xff1a;JADX是一个强大的反编译工具&#xff0c;它支持命令行和图形界面操作。除了基本的反编译功能外&#xff0c;JADX还提供了反混淆功能&#xff0c;有助于提高反编译后代码的可读性。 在Android开发和安全分析领域&#xff0c;反编译工具扮演着至关重要的角色。这…

怎么搭建一款看广告赚钱app游戏

搭建看广告赚钱软件是一个涉及多个方面的复杂过程&#xff0c;包括市场调研、功能规划、技术实现、用户体验优化以及合法合规与隐私保护等多个步骤。以下是一个大致的搭建流程&#xff1a; 市场调研与定位&#xff1a;首先&#xff0c;你需要进行市场调研&#xff0c;了解目标…

6月4(信息差)

&#x1f30d;AI预测极端天气提速5000倍&#xff01;微软发布Aurora&#xff0c;借AI之眼预测全球风暴 &#x1f384;理解老司机&#xff0c;超越老司机&#xff01;LeapAD&#xff1a;具身智能加持下的双过程自驾系统&#xff08;上海AI Lab等&#xff09; 论文题目&#xf…

手把手教你发布你的第一个npm插件包

在开源的世界里&#xff0c;npm&#xff08;Node Package Manager&#xff09;不仅是JavaScript生态中不可或缺的一部分&#xff0c;也是全球最大的软件注册表&#xff0c;它使得分享和复用代码变得异常简单。如果你有一个很棒的想法或者实用的功能想要封装成一个npm包供他人使…

详解 Scala 的隐式转换

当编译器第一次编译失败的时候&#xff0c;会在当前的环境中查找能让代码编译通过的方法&#xff0c;用于将某个类型进行转换&#xff0c;实现二次编译通过 一、隐式函数 隐式函数可以在不修改任何代码的情况下&#xff0c;扩展某个类的功能 /**声明语法&#xff1a;implicit d…

带池化注意力 Strip Pooling | Rethinking Spatial Pooling for Scene Parsing

论文地址:https://arxiv.org/abs/2003.13328 代码地址:https://github.com/houqb/SPNet 空间池化已被证明在捕获像素级预测任务的长距离上下文信息方面非常有效,如场景解析。在本文中,我们超越了通常具有N N规则形状的常规空间池化,重新思考空间池化的构成,引入了一种…

Docker安装MySQL8.0报错记录

Linux已知有docker MySQL5.6版本&#xff0c;再安装MySQL8.0&#xff0c;报错信息记录如下 Docker安装MySQL8.0报错记录 Linux已知有docker MySQL5.6版本&#xff0c;再安装MySQL8.0&#xff0c;报错信息记录如下 问题1 &#xff1a;ls: cannot access ‘/docker-entrypoint…