620 likes | 712 Views
Oracle8 i 新特性. 对象关系数据库. 1.1 传统关系模型的缺点 1.2 面向对象( oop) 的基本概念 1.3 对象类型( object) 1.4 收集类型( collection) 1.5 对象视图( object view). 认识 抽象. 数据模型是模型化数据和信息的工具。. 现实世界. 信息世界-概念模型. 转换. 机器世界- DBMS 支持的数据 模型. 系主任. 1 1. 领导. 系. E-R 图转换成关系模式. 1 : 1. 系(系名,类别,系主任). 系主任 ( 工作证号, 姓名, 年龄). 班级.
E N D
对象关系数据库 1.1 传统关系模型的缺点 1.2 面向对象(oop)的基本概念 1.3 对象类型(object) 1.4 收集类型(collection) 1.5 对象视图(object view)
认识 抽象 • 数据模型是模型化数据和信息的工具。 现实世界 信息世界-概念模型 转换 机器世界- DBMS支持的数据模型
系主任 1 1 领导 系 E-R图转换成关系模式 1 : 1 系(系名,类别,系主任) 系主任 ( 工作证号, 姓名, 年龄)
班级 1 N 包括 学生 E-R图转换成关系模式 1 : N 班级(班号,班主任,系) 学生(学号,姓名,性别,班号)
学生 M N 选课 课程 E-R图转换成关系模式 M : N 学生(学号,姓名,性别,班号) 课程(课号,课名,学分) 选课(学号,课号,成绩) 成绩 实体集 - 关系 联系-关系:由联系的各实体集主码属性, 以及联系本身的属性组成。
关系模型的特点 • 关系模型的概念单一,实体和联系都是用关系来表示 • 关系必须是规范化的关系,要求每一分量不可再分 • 支持关系语言,具有高度非过程化,支持集合运算 • 通过外来码实现联系 • 关系模型有严格的数据基础
复杂属性只能拆分成并列的单一属性 无法表示变长的属性 无法直接表示嵌套表 必须大量使用JOIN来实现多表查询 传统关系模型存在的缺陷
类和对象 方法和封装 继承和子类 多态性 1.2 面向对象(oop)的基本概念
类(Class)或抽象数据类型(ADT): 是具有相同特征的事物的抽象表示 类的属性或特征 类的方法 对象是类的一个实例 当前流行的程序设计方法: 类:按钮 属性:大小、TEXT 方法:clicked 对象:一个确认按钮 类和对象
方法是操纵对象类型的过程 方法用于封装对象 封装是对对象的一种保护方法,它决定着对象如何被访问 封装对用户和开发人员隐藏了底层开发的细节 方法和封装
任何对象类型可以通过创建子类的方法定义,子类延用了上级的属性任何对象类型可以通过创建子类的方法定义,子类延用了上级的属性 用继承实现代码重用 继承和子类 Entity Round Angle Polyangle Triangle Circle Ecllipse Rectangle
扩充的类型系统 Oracle是一个开放的类型系统,增加了复杂的数据类型以及用户自定义类型 用户定义的数据类型使得可以在数据库中为现实世界的对象建模 应用逻辑从应用程序中移动到数据库中 1.3 对象类型
对象类型必须包含一个或多个属性 属性的类型可以是Oracle的原始数据类型、LOB、对象、对象的引用REF、收集COLLECTION 可以有1个或多个方法 对象类型不存储数据;必须创建相应的表来存储数据 对象类型
例子:定义对象类型 CREATE TYPE name_type AS OBJECT ( first_name VARCHAR2(30), last_name VARCHAR2(30)); CREATE TYPE address_type AS OBJECT ( street VARCHAR2(30), city VARCHAR2(20), zip VARCHAR2(7)); 对象类型
CREATE TYPE cust_type AS OBJECT( custid NUMBER, invoice VARCHAR2(1), name name_type, address address_type); CREATE TABLE customer ( custid NUMBER PRIMARY KEY, name NAME_TYPE, address address_type); CREATE TABLE customers OF cust_type (custid PRIMARY KEY); 对象类型
对象存储:包含嵌套对象类型的表的存储是顺序的,类似于关系表的存储 custid, invoice, name.first_name, name.last_name, address.street, address.city, address.zip custid, invoice, name.first_name, name.last_name, address.street, address.city, address.zip 对象类型
对象类型的DDL命令 CREATE TYPE,CREATE TYPE BODY DROP TYPE ,DROP TYPE BODY ALTER TYPE,ALTER TYPE BODY (不能增加属性,只能增加方法或编译类型) GRANT/REVOKE EXECUTE ON TYPE 对象类型
CREATE TYPE name_type AS OBJECT ( first_name VARCHAR2(30), last_name VARCHAR2(30) ) ; CREATE TABLE customers OF name_type; SELECT REF(C) FROM customers c; 对象类型--行对象
对象表的一行代表对象类型的一个实例 对象表的列对应于对象类型的属性 每一个实例有系统产生的唯一的OID 对象ID(OID)是每一个行对象的唯一描述符,是全局唯一的,并且自动索引 但OID不用于定位数据, 而ROWID用于定位数据 包含OID的对象实例可以被引用(REF) 对象类型--行对象
对象类型可以定义为列的数据类型 存储在列中的类型实例没有OID,而且不能被引用 CREATE TABLE employees ( custid number, invoice varchar2(1), name name_type, address address_type); 对象类型--列对象
对象索引 索引列必须为基本类型 构造数据 对象属性和方法的引用 采用.引用方式引用对象的属性和方法 对象属性和方法的引用必须使用表的别名,而不能是实际的表名 对象类型 INSERT INTO employees VALUES(1, ‘a’, name_type(‘Jone’,’Jackson’), address_type(‘s’,’c’,’z’)); SELECT c.name.first_name, c.name.last_name FROM employees c;
CREATE TYPE cust_type AS OBJECT ( custid number, invoice varchar2(1), name name_type, address address_type ) ; CREATE TABLE customers of cust_type (custid PRIMARY KEY ) ; 对象类型--REF举例 为每行产生 一个OID INSERT INTO customers VALUES (1, '1', name_type('Jone','Jackson'), address_type('st','ci','11')); SELECT REF(s) FROM customers s;
CREATE TABLE orders ( orderid number, orderdate date, status varchar2(4), customer REF cust_type, qty number, partno number REFERENCES parts ) ; 对象类型--REF举例 区别外码引用 和REF
对象引用(REF): 是系统产生的用于定位OID的值 REF在引用表中存储被引用表内的OID 是指向行对象的指针, 易于实现表和表之间的联系,对象之间访问被引用的对象不再需要关系JOIN 将对象表的表别名作为REF的参数可以取得REF的值 只能用于具有OID的对象 . 用于对象引用 对象类型--对象引用REF
INSERT INTO orders SELECT 2, '7-10月-99', '2222', ref(c), 1000 FROM customers c WHERE c.custid=1; UPDATE orders o SET o.customer = ( SELECT REF( c ) FROM customers c WHERE custid = 2 ) WHERE o.orderid = 1 ; SELECT o.customer FROM orders o WHERE o.orderid = 1; 对象类型--REF举例 .name .first_name
DEREF 用于返回被引用对象中的数据 将包含REF的对象表列作为阐述可以取得对象的数据 SELECT DEREF( o.customer ) FROM orders o WHERE orderid = 1 ; 对象类型--对象引用REF
在关系设计中, 开发人员必须使用联合(JOIN) SELECT o.orderid, c.name FROM orders o, customers c WHERE c.custid = o.custid and c.custid =1; 服务器管理对象间的关系,用户只需通过属性进行引用 SELECT o.orderid, o.customer.name, o.status FROM orders o WHERE o.customer.custid = 1; 对象类型--REF简化了代码
VALUE用于从对象表中取得对象实例 取得的对象实例必须被相同类型的对象变量接收 不使用VALUE, SELECT只能返回一个对象的各个列值 DECLARE cust_variable cust_type; BEGIN SELECT VALUE( c ) INTO cust_variable FROM customers c WHERE custid = 789 ; END; VALUE使用对象表中的 实例初始化PL/SQL变量 对象类型--VALUE
方法是一个过程或函数, 是对象类型定义的一部分 对象类型总是有1到多个方法 方法的种类 成员方法 (member) 构造子方法 (constructor) MAP或ORDER方法 对象类型--方法
用户编写的用于操纵对象类型属性的子程序 成员方法可以带输入输出参数 对象类型有0到多个成员方法 执行方法的格式为: <对象名称>.<方法名称>([参数列表]) 对象类型--成员方法 CREATE TYPE employee_type AS OBJECT( empno number, ename varchar2(30), hiredate date, MEMBER FUNCTION days_at_company RETURN number);
CREATE TYPE BODY employee_type AS MEMBER FUNCTION days_at_company RETURN NUMBER IS BEGIN RETURN floor(sysdate - hiredate); END; END; CREATE TABLE employees OF employee_type; INSERT INTO employees VALUES (1, ‘Jone’, ‘10-10月-89’); select c.days_at_company() from employees c where c.id=1; 对象类型--成员方法
DECLARE emp_variable employee_type; days_employed number; BEGIN SELECT VALUE( e ) INTO emp_variable FROM employees e WHERE e.empno = 801 ; days_employed := emp_variable.days_at_company() ; dbms_output.put_line(‘Days employed: ‘ || to_char(days_employed)) ; END; 对象类型--执行方法(例)
构造子方法初始化一个对象类型的实例, 并将它的属性赋值 每一个对象类型自动包含一个构造子方法 构造子方法的名称采用对象名 构造子方法的参数即对象类型的所有属性 CREATE TYPE name_type AS OBJECT ( first_name VARCHAR2(30), last_name VARCHAR2(30) ); 对象类型--构造子方法
CREATE TYPE address_type AS OBJECT ( street VARCHAR2(30), city VARCHAR2(20), zip VARCHAR2(7) ); 对象类型--构造子方法
CREATE TYPE cust_type AS OBJECT ( custid number, invoice varchar2(1), name name_type, address address_type ); CREATE TABLE customers of cust_type (custid PRIMARY KEY); INSERT INTO customers VALUES ( 1, N, name_type(‘Jim’,’ Smith’), address_type(‘Main Street’, ‘New York’, ‘10010’) ); 构造子初始化对象类型, 为各个属性赋值 对象类型--使用构造子方法
传统的数据类型(如: number, date)易于排序和比较 对象类型由于结构复杂, 必须借助方法实现排序和比较 MAP方法将对象类型转换为传统数据类型 ORDER方法比较两个对象实例, 返回1, 0, -1 一个对象类型只能有一个MAP方法或一个ORDER方法 对象类型--排序和比较对象
MAP方法 方法返回一个传统数据类型用于排序 没有输入参数(有一个隐含参数) 被隐含调用, 以决定下面表达式的结果 相等 , 小于, 大于的比较 BETWEEN 和 IN的判断 ORDER BY, GROUP BY 子句 UNIQUE和PRIMARY KEY约束 对象类型--排序和比较对象
CREATE TYPE name_type AS OBJECT ( first_name varchar2(30), last_name varchar2(30), MAP MEMBER FUNCTION name_map RETURN varchar2 ); CREATE TYPE BODY name_type AS MAP MEMBER FUNCTION name_map RETURN varchar2 IS BEGIN RETURN last_name || first_name; END; END; 任何基于name_type类型 定义的表按名称的拼接串 作为排序和比较的依据
create table customers (custid number primary key, name name_type); insert into customers values (1, name_type('Mike','Jackson')); insert into customers values (2, name_type('Alice','Smith')); MAP方法隐含调用 对象类型--排序和比较对象 SELECT c.custid FROM customers c ORDER BY c.name ;
ORDER方法 决定类型实例的序列关系 有一个参数(外加一个隐含的参数) 返回一个整数 如果当前对象比比较对象小, 返回 -1 如果当前对象与比较对象相等, 返回 0 如果当前对象比比较对象大, 返回 1 对象类型--排序和比较对象
实现一对多关系的模型化 在关系设计中只能通过联接(JOIN)实现表的关联, 将导致复杂的运算 在对象设计中可以通过收集实现对象类型的关联(嵌套表), 定义一次,使用多次 排序或不排序的收集类型 数组 (Arrays 排序的收集) 嵌套表 (不排序的收集) 1.4 收集类型
数组 支持有序的一对多的关系 数组元素的类型: 基本类型或对象类型 变长的数组: VARRAY 元素具有相同类型 可以得到VARRAY中当前的元素总数 应指定最大容量 元素不能为嵌套表或VARRAY 收集类型--数组
CREATE TYPE phone_number_type AS OBJECT ( line_code VARCHAR2(10), phone_number VARCHAR2(40) ); CREATE TYPE phone_list_type AS VARRAY(7) OF phone_number_type; CREATE TYPE customer_type AS OBJECT ( custid NUMBER, name VARCHAR2(50), address address_type, contact VARCHAR2(50), phone_nums phone_list_type, MEMBER FUNCTION add_phone(new_phone phone_number_type) RETURN phone_list_type, ) ;
CREATE TYPE BODY customer_type AS MEMBER FUNCTION add_phone (new_phone phone_number_type) RETURN phone_list_type IS temp_array phone_list_type; counter INTEGER; BEGIN temp_array := SELF.phone_nums; counter := temp_array.COUNT +1; temp_array.EXTEND; temp_array(counter) := new_phone ; delete * from emp; commit; RETURN temp_array; END; END; CREATE TABLE customers OF customer_type;
INSERT INTO customers VALUES (8901, ‘Oracle Corp’, address_type(‘500 way’, ‘CA’, 94002), ‘Jim Smith’, phone_list_type( phone_number_type(‘Phone’, ‘506-0000’), phone_number_type(‘Fax’, ‘506-0001’) ) ); UPDATE customers c SET c.phone_nums = c.add_phone(phone_number_type(‘Cell’, ‘506-9999’)) WHERE c.custid = 8901; 收集类型--变长数组(例)
收集(collection)的方法: 内置的函数和过程 (见PL/SQL手册) EXISTS COUNT LIMIT FIRST and LAST PRIOR and NEXT EXTEND TRIM DELETE 收集类型--收集的方法
编译软件包中的函数或过程时, 可以使用PRAGMA编译指令通知PL/SQL编译器禁止对表中的数据和过程中的变量读或修改, 当出现违反情况时, 编译出错 格式: PRAGMA RESTRICT_REFERENCES ( function_name, WNDS [, WNPS] [, RNDS] [, RNPS]); WNDS ”不允许写数据库” RNDS “不允许读数据库” WNPS “不允许写程序包” RNPS “不允许读程序包, 即不允许引用程序包变量” 编译指令
嵌套表 嵌套表是包含在其它表中的表 每一个嵌套表记录逻辑上是一个单独的表, 但物理上只创建一个表存储各个嵌套表的所有记录 支持无序的一对多的关系 元素类型: 基本类型集或对象集 查询通过对主表的查询来完成 可以索引嵌套表的列 收集类型-嵌套表