定义对象表
对象表就像普通的表一样,只是存储的是对象类型,该表的每一个字段与对象的一个属性相对应。对象表的每一条记录存储一个对象类型的实例。语法如下:
CREATE TALE table_name OF object_type;
对象表基于的是系统定义的构造函数,而不是用户定义的构造函数,所以在向对象表插入数据时,必须要在构造函数中提供匹配的所有的属性值。
创建的对象表一旦引用了特定的对象类型,就不能使用DROP TYPE删除对象类型。
插入对象表
以上一篇文章中创建的employee_personobj
为例,我们先来创建一个对象表:
CREATE TABLE emp_obj_table OF employee_personobj;
然后插入数据:
INSERT INTO emp_obj_table VALUES('张小五','F',
TO_DATE('1983-01-01','YYYY-MM-DD'),
'中信',7981,5000,'Programmer');
也可以这样插入数据:
DECLARE
o_emp employee_personobj; --定义员工对象类型的变量
BEGIN
--使用构造函数实例化员工对象
o_emp:=employee_personobj('张小五','F',
TO_DATE('1983-01-01','YYYY-MM-DD'),
'中信',7981,5000,'Programmer');
INSERT INTO emp_obj_table VALUES(o_emp); --插入到对象表中
END;
检索对象表
除了使用跟传统的关系表检索数据一样的方法外,对象表还有VALUE和REF函数这两种检索方法。
VALUE函数
在查询语句中使用VALUE函数将返回存储在对象表中的对象实例。
比如查询单行:
DECLARE
o_emp employee_personobj; --定义一个对象类型的变量
BEGIN
--使用SELECT INTO语句将VALUE函数返回的对象实例插入到对象类型的变量
SELECT VALUE(e) INTO o_emp FROM emp_obj_table e WHERE e.person_name='张小五';
--输出对象类型的属性值
DBMS_OUTPUT.put_line(o_emp.person_name||'的职位是:'||o_emp.job);
END;
查询多行:
DECLARE
o_emp employee_personobj; --定义对象类型的变量
CURSOR all_emp
IS
SELECT VALUE (e) AS emp
FROM emp_obj_table e; --定义一个游标,用来查询多行数据
BEGIN
FOR each_emp IN all_emp --使用游标FOR循环检索游标数据
LOOP
o_emp := each_emp.emp; --获取游标查询的对象实例
--输出对象实例信息
DBMS_OUTPUT.put_line (o_emp.person_name || ' 的职位是:' || o_emp.job);
END LOOP;
END;
REF函数
REF和VALUE的区别在于REF返回的是指向对象实际位置的一个指针,而VALUE是把对象副本从一个子程序传递到另一个子程序。
看代码,我们先来使用REF创建引用关系:
CREATE TYPE address AS OBJECT ( --创建地址类型
street VARCHAR2 (35),
city VARCHAR2 (15),
state CHAR (2),
zip_code INTEGER
);
CREATE TABLE addresses OF address; --创建地址对象表
CREATE TYPE person AS OBJECT ( --创建人员对象类型
person_name VARCHAR2 (15),
birthday DATE,
home_address REF address, --使用REF关键字,指定属性为指向另一个对象表的对象
phone_number VARCHAR2 (15)
);
CREATE TABLE persons OF person; --创建人员对象表
然后向addresses对象表中插入数据:
--插入地址
INSERT INTO addresses
VALUES (address ('玉兰', '深圳', 'GD', '52334'));
INSERT INTO addresses
VALUES (address ('黄甫', '广州', 'GD', '52300'));
接下来向persons对象表插入数据,我们将使用 REF函数,通过REF函数返回的对addressed表中特定对象的引用,插入到persons表中:
--插入一个人员,注意这里的home_address部分是如何插入一个ref address的。
INSERT INTO persons
VALUES (person ('王小五',
TO_DATE ('1983-01-01', 'YYYY-MM-DD'),
(SELECT REF (a)
FROM addresses a
WHERE street = '玉兰'),
'16899188'
));
也可以这样插入:
--也可以用下面的过程来插入一个人员记录
DECLARE
addref REF address;
BEGIN
SELECT REF (a)
INTO addref
FROM addresses a
WHERE street = '玉兰'; --使用SELECT INTO查询一个引用对象
--使用INSERT语句向persons表中插入引用对象
INSERT INTO persons
VALUES (person ('五大狼',
TO_DATE ('1983-01-01', 'yyyy-mm-dd'),
addref,
'16899188'
));
END;
当对象表中包含引用类型时,如果直接使用SELECT语句进行查询,引用类型的列将会是一串数字码,而且引用类型的对象无法直接访问其属性。需要使用DEREF函数,才可以查询到引用类型所指向的地址类型的值,如:
SELECT person_name, DEREF (home_address) FROM persons;
更新对象表
可以像更新普通表一样更新对象表:
UPDATE emp_obj_table empobj
SET empobj.gender = 'M'
WHERE empobj.person_name = '张小五';
也可以直接更新对象表中的一个对象实例:
UPDATE emp_obj_table empobj
SET empobj=employee_personobj('李小七','F',
TO_DATE('1983-01-01','YYYY-MM-DD'),
'众泰',7981,7000,'Testing')
WHERE person_name='张小五';
还可以在WHERE条件中使用REF函数来获取对象的标识符(对象标识符是对象表中为了唯一标识一条记录而定义的一串数字值),来更新数据:
DECLARE
emp_ref REF employee_personobj; --定义引用对象类型
BEGIN
SELECT REF(e1)
INTO emp_ref
FROM emp_obj_table e1
WHERE person_name = '刘小艳'; --从对象表中获取对刘小艳的对象引用
UPDATE emp_obj_table emp_obj
SET emp_obj =employee_personobj('何小凤',
'F',TO_DATE ('1985-08-01', 'YYYY-MM-DD'),
'本甜',7981, 7000, 'developer')
WHERE REF (emp_obj) = emp_ref; --使用UPDATE语句更新emp_obj_table表中刘小艳的记录
END;
如果对象表的属性列表中包含了引用类型,而我们需要修改其列所引用的数据,就必须修改相应的 行对象。例如在persons表中,hone_address
字段是一个指向address对象类型的引用,因此如果要UPDATE这个包含引用类型的表,可以这么做:
DECLARE
addr address;
BEGIN
SELECT DEREF(home_address) INTO addr FROM persons WHERE person_name='王小五';
addr.street:='五一';
UPDATE address SET street=addr.street WHERE zip_code='523330';
END;
删除对象表
如:
DELETE FROM emp_obj_table WHERE person_name='张小五';
也可以这样:
DECLARE
emp_ref REF employee_personobj; --定义引用对象类型
BEGIN
SELECT REF(e1)
INTO emp_ref
FROM emp_obj_table e1
WHERE person_name = '刘小艳'; --从对象表中获取对刘小艳的对象引用
DELETE FROM emp_obj_table emp_obj
WHERE REF (emp_obj) = emp_ref; --使用DELETE语句删除emp_obj_table表中刘小艳的记录
END;
创建对象列
除了将整个对象作为表中的列来存储的对象表之外,还可以为关系对中的某一列的属性指定为对象类型,这种表称为带对象列的关系表。
这个比较简单,这里就不举例。
使用对象视图
对象视图可以让我们使用面向对象的特性来操作关系型数据结构,如果想将已存在的关系型的数据更改为使用OOP(面向对象)的操作方式,使用对象视图非常有用。为了创建一个对象视图,必须首先创建一个与底层数据表的列具有相匹配属性的对象类型。
举个例子,要以对象的方式操作emp表,可以先基于emp表的表列定义一个对象类型,下面我们来定义个emp_tbl_obj
,用来匹配对emp表的操作:
--定义与关系表emp相匹配列的对象类型
CREATE OR REPLACE TYPE emp_tbl_obj AS OBJECT (
empno NUMBER (6),
ename VARCHAR2(10),
job VARCHAR2(18),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2),
MEMBER FUNCTION get_emp_info
RETURN VARCHAR2
)
INSTANTIABLE NOT FINAL;
/
--定义对象类型体
CREATE OR REPLACE TYPE BODY emp_tbl_obj AS
MEMBER FUNCTION get_emp_info RETURN VARCHAR2 IS
BEGIN
--在对象类型体中可以直接访问在父对象中定义的属性
RETURN '员工编号:'||SELF.empno||' 员工名称:'||SELF.ename||' 职位:'||SELF.job;
END;
END;
/
接下来就可以创建一个基于该对象类型的视图。在创建对象视图时,必须要确定要使用的OID(对象标识符)。对象标识符是用来唯一标识一行对象的一个字符串,通过OID可以保证对对象实例引用的唯一性。OID仅在对象表和对象视图上被创建,一旦一个OID被赋给了一个对象,那么将永远属于那个对象。通常情况下,Oracle会自动产生OID值,不需要手工产生,但在定义对象视图时,可以覆盖系统产生OID的机制,更改为使用对象表的额主键来替代。
下面来创建基于emp_tbl_obj
的对象类型的emp表的对象视图:
--创建emp_view对象视图
CREATE VIEW emp_view
OF emp_tbl_obj
WITH OBJECT IDENTIFIER (empno)
AS
SELECT e.empno, e.ename, e.job, e.mgr, e.hiredate, e.sal, e.comm, e.deptno
FROM emp e;
在创建了这个对象视图以后,就可以用前面介绍的对象操作语法来操作对象了:
DECLARE
o_emp emp_tbl_obj; --定义对象类型的变量
BEGIN
--查询对象类型
SELECT VALUE(e) INTO o_emp FROM emp_view e WHERE empno=7369;
--输出对象类型的属性
DBMS_OUTPUT.put_line('员工'||o_emp.ename||' 的薪资为:'||o_emp.sal);
DBMS_OUTPUT.put_line(o_emp.get_emp_info); --调用对象类型的成员方法
END;