精通Oracle10编程SQL(15)使用对象类型

/*
 *使用对象类型
 */
--建立和使用简单对象类型
--对象类型包括对象类型规范和对象类型体两部分。
--建立和使用不包含任何方法的对象类型
CREATE OR REPLACE TYPE person_typ1 as OBJECT(
  name varchar2(10),gender varchar2(4),birthdate date
);

drop type person_typ1;

--建立行对象(基于对象类型person_typ1)
--行对象是指直接基于对象类型所建立的表
--下面这条命令会建立行对象person_tab1
create table person_tab1 of person_typ1;

drop table person_tab1;

--行对象结构与普通表没有任何区别
select * from person_tab1;

--为行对象插入数据
begin
     insert into person_tab1 values('马丽','女','11-1月-76');
     --对象类型的构造方法来插入数据
     insert into person_tab1 values(person_typ1('王鸣','男','12-4月-76'));
end;

--检萦行对象数据
--如果要将数据检萦到对象类型变量中,则必须要使用函数VALUE取得行对象数据
DECLARE
   person person_typ1;
begin
   select value(p) into person from person_tab1 p where p.name='&name';
   dbms_output.put_line('性别:'||person.gender);
   dbms_output.put_line('出生日期:'||person.birthdate);
end;

--更新行对象数据
--更新行对象数据时如果按照对象属性更新数据,则必须要为行对象定义别名。
begin
   update person_tab1 p set p.birthdate='11-2月-76' where p.name='马丽';
end;

--删除行对象数据
--删除行对象数据时如果按照对象属性删除数据,则必须要为行对象定义别名。
begin
   delete from person_tab1 p where p.name='马丽';
end;


--建立列对象(包含对象类型person_typ1)
--列对象是指在建表时指定了对象类型列的对象表
CREATE TABLE employee_tab1(
   eno number(6),person person_typ1,
   sal number(6,2),job varchar2(12)
);

drop table employee_tab1;

select * from employee_tab1;

--为列对象employee_tab1插入数据
--为列对象插入数据时必须要使用对象类型的构造方法为对象列提供数据
BEGIN
     insert into employee_tab1(eno,sal,job,person) values(1,2000,'高级钳工',person_typ1('王鸣','男','01-8月-76'));
END;

--检索对象类型列的数据
--检萦行对象数据到对象类型变量时必须要使用VALUE函数,而检索列对象的对象类型列数据时可以直接将对象实例数据检索到对象类型变量中
DECLARE
   employee person_typ1;
   salary number(6,2);
begin
   select person,sal into employee,salary from employee_tab1 where eno=&no;
   dbms_output.put_line('雇员名:'||employee.name);
   dbms_output.put_line('雇员工资:'||salary);
end;

--更新对象列数据
begin
   update employee_tab1 p set p.person.birthdate='&newdate'
      where p.person.name='&name';
end;

--依据对象属性删除数据
begin
   delete from employee_tab1 p where p.person.name='王鸣';
end;


--建立和使用包含MEMBER方法的对象类型
--建立对象类型规范person_typ2如下
create or replace type person_typ2 as object(
   name varchar2(12),gender varchar2(4),
   birthdate date,address varchar2(100),
   member procedure change_address(new_addr varchar2),
   member function get_info return varchar2
);

drop type person_type2;

--建立对象类型体person_typ2的示例如下
CREATE OR REPLACE TYPE BODY person_typ2 is
   member procedure change_address(new_addr varchar2)
   is
   begin
     address:=new_addr;
   end;
   member function get_info return varchar2
   is
     v_info varchar2(100);
   begin
     v_info:='姓名:'||name||',出生日期:'||birthdate||',地址:'||address;
     return v_info;
   end;
end;

drop type body person_typ2;

--在完成了对象类型person_typ2的创建工作之后,就可以使用该对象类型了
--基于person_typ2建立对象表employee_tab2,并为其插入数据的示例如下
create table employee_tab2(
   eno number(6),person person_typ2,
   sal number(6,2),job varchar2(18)
);

select * from employee_tab2;

drop table employee_tab2;

insert into employee_tab2(eno,sal,job,person) values(1,2000,'高级焊工',person_typ2('王鸣','男','11-1月-75','深圳科技南路2号'));

insert into employee_tab2(eno,sal,job,person) values(2,1500,'质量检查员',person_typ2('马丽','女','11-5月-75','深圳科技南路20号'));

--下面以调用对象方法change_address改变人员地址为例,说明如何在PL/SQL块中使用对象方法
DECLARE
   v_person person_typ2;
begin
   select person into v_person from employee_tab2 where eno=&no;
   v_person.change_address('深圳龙岗坂田基地');
   update employee_tab2 set person=v_person where eno=&no;
   dbms_output.put_line(v_person.get_info);
end;

--建立和使用包含STATIC方法的对象类型
--建立对象类型规范person_typ3如下
CREATE OR REPLACE TYPE person_typ3 as object(
   name varchar2(10),gender varchar2(4),
   birthdate date,regdate date,
   static function getdate return date,
   member function get_info return varchar2
);

drop type person_typ3;

--建立对象类型体如下
CREATE OR REPLACE TYPE BODY person_typ3 is
  static function getdate return date is 
  begin
    return sysdate;
  end;
  member function get_info return varchar2
  is
  begin
    return '姓名:'||name||',注册日期:'||regdate;
  end;
end;

--基于对象类型person_typ3建立对象表employee_tab3,并为其插入数据的示例如下
CREATE TABLE employee_tab3(
   eno number(6),person person_typ3,
   sal number(6,2),job varchar2(18)
);

--因为建立对象类型时定义了STATIC方法和MEMBER方法,所以在PL/SQL块中可以引用这些方法
BEGIN
   insert into employee_tab3(eno,sal,job,person)
     values(&no,&salary,'&title',person_typ3(
       '&name','&sex','&birthdate',person_typ3.getdate()
   ));
END;

select * from employee_tab3;


--建立和使用包含MAP方法的对象类型
--MAP方法用于将对象实例映射为标量数值(NUMBER,DATE,VARCHAR2等)
--注意:一个对象类型最多只能定义一个MAP方法,并且MAP方法和ORDER方法不能同时使用
CREATE OR REPLACE TYPE person_typ4 as object(
   name varchar2(10),gender varchar2(4),birthdate date,
   map member function getage return varchar2
);

--建立对象类型体的示例
CREATE OR REPLACE type body person_typ4 is 
   map member function getage return varchar2
   is
   begin
      return trunc((sysdate-birthdate)/365);
   end;
end;

--基于对象类型person_typ4建立对象表employee_tab4并为其插入数据的示例如下
create table employee_tab4(
   eno number(6),person person_typ4,
   sal number(6,2),job varchar2(18)
);

insert into employee_tab4(eno,sal,job,person)
values(1,1500,'图书管理员',person_typ4(
'马丽','女','11-1月-76'));

insert into employee_tab4(eno,sal,job,person)
values(2,2000,'高级焊工',person_typ4(
'王鸣','男','11-5月-75'));

insert into employee_tab4(eno,sal,job,person)
values(3,2500,'高级工程师',person_typ4(
'李奇','男','11-5月-70'));

select * from employee_tab4;

--下面以比较对象表employee_tab4的前两条数据为例,说明使用MAP方法getage比较对象实例的方法
DECLARE
   TYPE person_table_type is table of person_typ4;
   person_table person_table_type;
   v_temp varchar2(100);
begin
   select person bulk collect into person_table from employee_tab4;
   if person_table(1).getage()>person_table(2).getage() then
      v_temp:=person_table(1).name||'比'||person_table(2).name||'大';
   else
      v_temp:=person_table(1).name||'比'||person_table(2).name||'小';
   end if;
   dbms_output.put_line(v_temp);
end;


--建立和使用包含ORDER方法的对象类型
--ORDER方法用于比较两个对象实例的大小
--注意:一个对象类型最多只能包含一个ORDER方法,并且ORDER方法不能与MAP方法同时使用
CREATE OR REPLACE TYPE person_typ5 as object(
name varchar2(10),gender varchar2(4),birthdate date,
order member function compare(p person_typ5)
return int);

create or replace type body person_typ5 is
   order member function compare(p person_typ5) return int
   is
   begin
       case
           when birthdate<p.birthdate then return 1;
           when birthdate=p.birthdate then return 0;
           when birthdate>p.birthdate then return -1;
       end case;
   end;
end;

--基于对象类型person_typ5建立对象表employee_tab5,并为其插入两条数据
create table employee_tab5(
   eno number(6),person person_typ5,
   sal number(6,2),job varchar2(18)
);

insert into employee_tab5(eno,sal,job,person)
values(1,1500,'图书管理员',person_typ5('马丽','女','11-1月-76'));

insert into employee_tab5(eno,sal,job,person)
values(2,2000,'高级焊工',person_typ5('王鸣','男','11-5月-75'));

select * from employee_tab5;

--下面以比较对象表employee_tab5的前两条数据为例,说明使用order方法compare比较对象实例的方法
DECLARE 
   TYPE person_table_type is table of person_typ5;
   person_table person_table_type;
   v_temp varchar2(100);
begin
   select person bulk collect into person_table from employee_tab5;
   if person_table(1).compare(person_table(2))=1 then
      v_temp:=person_table(1).name||'比'||person_table(2).name||'大';
   elsif person_table(1).compare(person_table(2))=0 then
      v_temp:=person_table(1).name||'和'||person_table(2).name||'一样大';
   else
      v_temp:=person_table(1).name||'比'||person_table(2).name||'小';
   end if;
   dbms_output.put_line(v_temp);
end;


--建立和使用包含自定义构造方法的对象类型
--注意,当自定义构造方法时,构造方法的名称必须要与对象类型的名称完全相同,并且必须要使用CONSTRUCTOR FUNCTION关键字定义构造方法
--建立对象类型person_typ6的示例如下
create or replace type person_typ6 as object(
   name varchar2(10),gender varchar2(4),birthdate date,
   constructor function person_typ6(name varchar2) return self as result,
   constructor function person_typ6(name varchar2,gender varchar2) return self as result,
   constructor function person_typ6(name varchar2,gender varchar2,birthdate date) return self as result
);

--建立对象类型体实现其构造方法
CREATE OR REPLACE TYPE BODY person_typ6 is 
   constructor function person_typ6(name varchar2) return self as result
   is
   begin
      self.name:=name;
      self.gender:='女';
      self.birthdate:=sysdate;
      return;
   end;
   
   constructor function person_typ6(name varchar2,gender varchar2) return self as result
   is
   begin
      self.name:=name;
      self.gender:=gender;
      self.birthdate:=sysdate;
      return;
   end;
   
   constructor function person_typ6(name varchar2,gender varchar2,birthdate date) return self as result
   is
   begin
      self.name:=name;
      self.gender:=gender;
      self.birthdate:=birthdate;
      return;
   end;
end;

--下面以基于对象类型person_typ5建立对象表,并使用各种构造方法为其插入数据为例,说明如何使用各种自定义构造方法
create table employee_tab6(
   eno number(6),person person_typ6,
   sal number(6,2),job varchar2(18)
);

insert into employee_tab6(eno,sal,job,person) values(1,1500,'图书管理员',person_typ6('马丽'));

insert into employee_tab6(eno,sal,job,person) values(2,2000,'高级钳工',person_typ6('王鸣','男'));

insert into employee_tab6(eno,sal,job,person) values(3,2500,'高级工程师',person_typ6('李奇','男','01-1月-70'));

select * from employee_tab6;


--建立和使用复杂对象类型
--简单对象类型是指独立的并且与其他对象类型无关的对象类型,而复杂对象类型是指与其他对象类型具有关联关系的对象类型
--对象类型嵌套
--下面以建立和使用对象类型addr_typ7和person_typ7为例,说明如何建立和使用嵌套对象类型
--建立对象类型addr_typ7
create or replace type addr_typ7 as object(
   state varchar2(20),city varchar2(20),
   street varchar2(50),zipcode varchar2(8),
   member function get_addr return varchar2
);

drop type addr_typ7;

create or replace type body addr_typ7 as 
   member function get_addr return varchar2 is
   begin
      return state||city||street;
   end;
end;

drop type body addr_typ7;

--建立对象类型person_typ7
create or replace type person_typ7 as object(
   name varchar2(10),gender varchar2(4),
   birthdate date,address addr_typ7,
   member function get_info return varchar2
);

drop type person_typ7;

create or replace type body person_typ7 as 
   member function get_info return varchar2
   is
   begin
      return '姓名:'||name||',家庭住址:'||address.get_addr();
   end;
end;

drop type body person_typ7;

--建立并操纵对象表employee_tab7
create table employee_tab7(
   eno number(6),person person_typ7,
   sal number(6,2),job varchar2(18)
);

drop table employee_tab7;

--操纵对象表employee_tab7
--1.在PL/SQL块中为对象表插入数据
begin
   insert into employee_tab7(eno,sal,job,person) values(1,1500,'图书管理员',person_typ7(
      '马丽','女','01-11月-76',addr_typ7(
      '内蒙古自治区','呼和浩特市','呼伦北路22号','010010')
   ));
   insert into employee_tab7(eno,sal,job,person) values(2,2000,'高级钳工',person_typ7(
      '王鸣','男','11-12月-75',addr_typ7(
      '内蒙古自治区','呼和浩特市','呼伦北路50号','010010')
   ));
end;

select * from employee_tab7;

--2.在PL/SQL块中更新对象列数据
DECLARE
   v_person person_typ7;
begin
   select person into v_person from employee_tab7 where eno=&no;
   v_person.address.street:='&street';
   update employee_tab7 set person=v_person where eno=&no;
end;

--3.在PL/SQL块中检索对象列数据
DECLARE
   v_person person_typ7;
begin
   select person into v_person from employee_tab7 where eno=&eno;
   dbms_output.put_line(v_person.get_info);
end;

--4.在PL/SQL块中删除对象表数据
begin
     delete from employee_tab7 where eno=&no;
end;


--参照对象类型
--参照对象类型是指在建立对象表时使用REF定义表列,REF实际是指向行对象数据的逻辑指针。
--下面以建立对象类型person_typ8、行对象person_tab8和对象表employee_tab8为例,说明如何使用参照对象类型
--建立对象类型person_typ8
CREATE OR REPLACE TYPE person_typ8 as object(
   name varchar2(10),gender varchar2(4),
   birthdate date,address varchar2(50),
   member function get_info return varchar2
);

create or replace type body person_typ8 as 
   member function get_info return varchar2
   is
   begin
      return '姓名:'||name||',家庭住址:'||address;
   end;
end;

--建立行对象person_tab8并追加数据
create table person_tab8 of person_typ8;

insert into person_tab8 values('马丽','女','11-1月-76','呼和浩特市北垣东街11号');

insert into person_tab8 values('王鸣','男','11-2月-76','呼和浩特市呼伦南路21号');

select * from person_tab8;

--建立对象表employee_tab8
--对象表employee_tab8用于存放雇员信息。因为person_tab8表已经包含了人员的部分信息,所以为了降低占用空间,employee_tab8表应该直接引用表person_tab8的数据
create table employee_tab8(
   eno number(6),person ref person_typ8,
   sal number(6,2),job varchar2(18)
);

drop table employee_tab8;

select * from employee_tab8;

--操纵对象表employee_tab8
--1.为对象表插入数据
begin
   insert into employee_tab8
   select 1,ref(a),2000,'图书管理员' from person_tab8 a where a.name='马丽';
   insert into employee_tab8
   select 2,ref(a),2200,'高级钳工' from person_tab8 a where a.name='王鸣';
end;

--2.检索REF对象列数据
--检索REF对象列数据时,因为该列实际存放的是指向行对象数据的指针,所以为了取得行对象的相应数据,必须要使用DEREF函数取得REF列所对应的实际数据
DECLARE
   v_person person_typ8;
begin
   select deref(person) into v_person from employee_tab8 where eno=&no;
   dbms_output.put_line(v_person.get_info);
end;

--3.更新REF对象列数据
DECLARE
  v_person person_typ8;
begin
  select deref(person) into v_person from employee_tab8 where eno=&no;
  v_person.address:='&address';
  update person_tab8 set address=v_person.address where name=v_person.name;
end;

select * from person_tab8;

select * from employee_tab8;

--删除对象表数据
begin
   delete from employee_tab8 where eno=&no;
end;


--对象类型继承
--当使用对象类型继承时,在定义父类型时必须要指定NOT FINAL选项,如果不指定该选项,默认选项为FINAL,表示该对象类型不能被继承
--下面以建立父类型person_typ9,子类型employee_typ9,对象表employee_tab9为例,说明使用对象类型继承的方法
--建立父对象类型person_typ9
CREATE OR REPLACE type person_typ9 as object(
   name varchar2(10),gender varchar2(4),
   birthday date,address varchar2(50),
   member function get_info return varchar2
) not final;

drop type person_typ9;

create or replace type body person_typ9 as 
   member function get_info return varchar2
   is
   begin
      return '姓名:'||name||',家庭住址:'||address;
   end;
end;

drop type body person_typ9;

--建立子对象类型employee_typ9
create or replace type employee_typ9 under person_typ9(
   eno number(6),sal number(6,2),job varchar2(18),
   member function get_other return varchar2
);

drop type employee_typ9;

create or replace type body employee_typ9 as
   member function get_other return varchar2
   is
   begin
      return '雇员名称:'||name||',工资:'||sal;
   end;
end;

drop type body employee_typ9;


--建立并操纵对象表employee_tab9
--1.建立对象表并插入数据
create table employee_tab9 of employee_typ9;

drop table employee_tab9;

select * from employee_tab9;

insert into employee_tab9 values(
   '马丽','女','11-1月-76','呼和浩特市北垣东街11号',
   1,1500,'图书管理员'
);

insert into employee_tab9 values(
   '王鸣','男','11-2月-76','呼和浩特市呼伦南路21号',
   2,2200,'高级钳工'
);

select * from employee_tab9;

--使用对象方法输出数据
DECLARE
   v_employee employee_typ9;
begin
   select value(a) into v_employee from employee_tab9 a where a.eno=&no;
   dbms_output.put_line(v_employee.get_info);
   dbms_output.put_line(v_employee.get_other);
end;

--维护对象类型
--显示对象类型信息
--通过查询数据字典视图USER_TYPES,可以显示当前用户所包含的所有对象类型的信息。
--type_name用于标识对象类型的名称,attributes用于标识对象类型所包含的属性个数,而final用于标识对象类型是否可以作为父类型使用
select type_name,attributes,final from user_types;

select * from user_types;

--在SQL*Plus中,通过执行DESC命令可以查看对象类型所包含的属性和方法
DESC person_typ1;

--增加和删除对象类型属性
alter type person_typ1 add attribute address varchar2(50) cascade;

alter type person_typ1 drop attribute birthdate cascade;

--增加和删除对象类型方法
alter type person_typ1 add member function get_info return varchar2 cascade;

create or replace type body person_typ1 as
   member function get_info return varchar2 is 
   begin
      return '雇员名:'||name||',家庭住址:'||address;
   end;
end;

猜你喜欢

转载自bijian1013.iteye.com/blog/2222466