Object Type(属性、方法(构造/member/static/map/order)、行列对象表、REF数据类型、基本应用(语法/使用)、高级应用(嵌套/引用/继承)、显示信息、增删属性和对象


Oracle Object Type 对象类型

  • Oracle对象类型是Oracle面向对象程序设计的体现,它封装了数据结构和用于操纵这些数据结构的过程和函数。

对象类型的组成

  • 对象类型由两部分组成——对象类型头和对象类型体。
  • 对象类型头用于定义对象的公用属性和方法;对象类型体用于实现对象类型头所定义的公用方法

对象类型属性

  • 定义对象类型最少要包含一个属性,最多包含1000个属性。定义时必须提供属性名和数据类型,但不能指定默认值和not null
  • 数据类型不能包括long、long raw、rowid、urowid和PL/SQL特有类型(boolean%type%rowtype\ref cursor等)

对象类型的方法

  • 定义对象类型可以包含也可以不包含方法,可以定义构造方法、member方法、static方法、map方法和order方法。
构造方法
  • 用于初始化对象并返回对象实例。构造方法是与对象类型同名的函数,默认的构造方法参数是对象类型的所有属性。
  • 9i前只能使用系统默认的构造方法、9i后可自定义构造函数,自定义必须使用constructor function关键字
member方法
  • 用于访问对象实例的数据。当使用member方法时,可以使用内置参数self访问当前对象实例
  • 当定义member方法时,无论是否定义self参数,它都会被作为第一个参数传递给member方法
  • 但如果要定义参数self,那么其类型必须要使用当前对象类型。member方法只能由对象实例调用,而不能由对象类型调用。
static方法
  • 用于访问对象类型,可以在对象类型上执行全局操作,而不需要访问特定对象实例的数据,因此static方法引用self参数。
  • static方法只能由对象类型调用,不能由对象实例调用(和member相反)。
map方法
  • 对象类型不同于标量类型可以直接比较,为了按照特定规则排序对象实例的数据,可以定义map方法,但只能有一个,与order互斥。
order方法
  • map可以在对多个对象实例之间排序,而order只能比较2个实例的大小。 定义对象类型时最多只能定义一个order方法,
  • 而且map和order方法不能同时定义。使用原则是可不用则均不用,比较2个对象则用order,多个对象则用map。

对象表

  • 对象表是指至少包含一个对象类型列的表。分为行对象表和列对象表。
  • 行对象表是指直接基于对象类型所建立的表;列对象表则是包含一个或多个对象类型列的对象表

REF数据类型

  • ref是指向行对象的逻辑指针,是Oracle的一种内置数据类型。建表时通过使用REF引用行对象,可以使不同表共享相同对象
  • 例如:create table department(dno number(2),dname varchar2(10),emp ref
    employee_type)

Object Type的基本应用

Object Type的语法

--Object Type 类型头
create or replace type type_name as object
(
	v_name1 datatype[,v_name2 datatype,...],
	[member|static method1 spec,member|static method2 spec,...]
);

--Object Type 类型体
--如果定义对象类型头时没有定义方法,则不需要建立对象类型体。
create or replace type body type_name as
member|static method1 body;    --body是PL/SQL的方法实现代码。
member|static method1 body;
...

建立和使用不包含任何方法的Object Type

1)建立对象类型

--建立对象类型
create or replace type person_typ1 as object
(
	name varchar2(10),
	gender varchar2(2),
	birthdate date
);

2)对于行对象表

--建立行对象表
create table person_tab1 of person_typ1;

--插入
begin
	insert into person_tab1 values('马丽','女','11-1月-76');--不用构造方法
	insert into person_tab1 values(person_typ1('王鸣','男','12-2月-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||','||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;

3)对于列对象表

--建立列对象表
create table employee_tab1(eno number(6),person person_typ1,sal number(6.2),job varchar2(10));

--插入,必须使用构造方法(默认构造方法)
begin
	insert into employee_tab1(eno,sal,job,person) 
	values(1,2000,'高级电工',person_typ1('王鸣','男'.'01-8月-76'));
end;

--查询
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||','||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;

建立和使用包含方法的Object Type

1)建立对象类型头

create or replace type person_typ2 as object
(
	name      varchar2(10),
	gender    varchar2(2),
	birthdate date,
	address   varchar2(100),
	regdate   date,
	member procedure change_address(new_addr varchar2),    --member方法
	member function get_info return varchar2,              --member方法
	static function getdate return date,				   --static方法
	map member function getage return varchar2,            --map方法
	order member function compare(p person_typ2) return int,	--order方法
	constructor person typ2(name varchar2) return self as result,
	constructor person typ2(name varchar2,gender varchar2) return self as result
);

2)建立对象类型体

create or replace type body person_typ2 is
	member procedure change_address(new_addr varchar2) is
	begin
		address := new_addr; --member方法体现之处,直接访问修改对象实例的数据address
	end;
	
	member function get_info return varchar2 is
		v_info varchar2(100);
	begin
		v_info := name || ',' || birthdate || ',' || regdate;
		return v_info;
	end;
	
	static function gerdate return date is
	begin
		return sysdate;
	end;
	
	map member function getage return varchar2 is
	begin
		return trunc((sysdate-birthdate)/365);--比较的依据是按照时间
	end;
	
	order member function compare(p person_typ2) 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;
	
	constructor function person_typ2(name varchar2) return self as result is
	begin
		self.name:=name;
		self.gender:='女';
		self.birthdate:=sysdate;
		return;
	end;
	
	constructor function person_typ2(name varchar2,gender varchar2) return self as result is
	begin
		self.name:=name;
		self.gender:=gender;
		self.birthdate:=sysdate;
		return;
	end;
end;

3)建立列对象表

--建立列对象表
create table employee_tab2
(
	eno number(6),
	person person_typ2,
	sal number(6,2),
	job varchar2(10)
);

--插入
insert into employee_tab2(eno,sal,job,person) values(1,1500,'图书管理员',
	person_typ2('马丽','女','11-1月-75','呼和浩特11号',person_typ2.getdate()));--由对象类型调用的全局方法getdate(static方法)
insert into employee_tab2(eno,sal,job,person) values(2,2000,'高级焊工',
	person_typ2('王鸣','男','11-5月-75','呼和浩特21号',person_typ2.getdate()));
insert into employee_tab2(eno,sal,job,person) values(3,3000,'高级工程师',
	person_typ2('李奇','男','11-5月-70','呼和浩特31号',person_typ2.getdate()));
insert into employee_tab2(eno,sal,job,person) values(3,3000,'高级工程师',
	person_typ2('怪兽');--自定义构造方法
insert into employee_tab2(eno,sal,job,person) values(3,3000,'高级工程师',
	person_typ2('怪兽','男');

--调用
declare
	v_person person_typ2;
	type person_table_type is table of person_typ2;
	person_table person_table_type;
begin
	select person into v_person from employee_tab2 where eno = &no;
	v_person.change_address('呼和浩特12号');
	update employee_tab2 set person = v_person where eno = &no;
	dbms_output.put_line(v_person.get_info);
	
	--map,取表中前2条数据来对比
	select person bulk collect into person_table from employee_tab2;
	if person_table(1).getage()>person_table(2).getage() then
	  dbms_output.put_line(person_table(1).name||'比'||person_table(2).name||'大');
	else
	  dbms_output.put_line(person_table(2).name||'不比'||person_table(1).name||'大');
	end if;
	
	--compare
	if person_table(1).compare(person_table(2)) = 1 then
	  dbms_output.put_line(person_table(1).name||'比'||person_table(2).name||'大');
	else
	  dbms_output.put_line(person_table(2).name||'不比'||person_table(1).name||'大');
	end if;
end;

Object Type的高级应用

高级应用简述与其他对象类型具有关联关系的对象类型。包括对象类型的嵌套、对象类型的引用、对象类型的继承

Object Type的嵌套

1)建立对象类型addr_typ7

create or replace type addr_typ7 as object
(
	state varchar2(20),
	city varchar2(20),
	street varchar2(50),
	zip code(6),
	member function get_addr return varchar2
);


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

2)建立对象类型person_typ7,嵌套addr_typ7对象类型

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


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

3)建立列对象表employee_tab7

create table employee_tab7
(
	eno number(6),
	person person_typ7,    --
	sal number(6,2),
	job varchar2(10)
);

4)对对象表的增删改查

--插入
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')));

--更新
declare
	v_person person_typ7;
begin
	select person into v_person from employee_tab7 where eno=1;
	v_person.address.street:='北恒东街11号';
	update employee_tab7 set person=v_person where eno=1;
end;

--查询
declare
	v_person_typ7;
begin
	select person into v_person from employee_tab7 where eno=1;
	dbms_output.put_line(v_person.get_info);
end;

--删除
begin
   delete from employ33_tab7 where eno=1;
end;

Object Type的引用

参照对象类型是指在建立对象表时使用REF定义表列,REF实际是指向行对象表数据的指针。
通过使用REF定义表列,可以使得一个对象表引用另一个对象表(行对象表)的数据

1)建立对象类型person_typ8

create or replace type person_typ8 as object
(
	name varchar2(10),
	gender varchar2(2),
	birthdate date,
	address varchar2(100),
	member function get_info return varchar2
);


create or replace type body person_typ8 as
	member function get_info return varchar2 is
	begin
		return name||',0'||address;
	end;
end;

2)建立行对象表person_tab8

create table person_tab8 of person_typ8;
insert into person_tab8 values('马丽','女','11-1月-75','呼和浩特11号');
insert into person_tab8 values('王鸣','男','11-5月-75','呼和浩特21号');

3)建立列对象表employee_tab8

create table employee_tab8
(
	eno number(6),
	person ref person_typ8,    --说明:employee_tab8表直接引用person_tab8表的数据。
	sal number(6,2),
	job varchar2(10)
);

4)对对象表employee_tab8进行增删改查

--插入
--说明:因为employee_tab8的定义使用ref引用了person_tab8,所以插入需要引用该表数据。使用函数REF
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),2000,'高级钳工' from person_tab8 a where a.name='王鸣';
end;

--查询
--说明:取ref对象列数据,必须使用deref。
declare
	v_person person_typ8;
begin
	select deref(person) into v_person from employee_tab8 where eno=1;
	dbms_output.put_line(v_person.get_into);
end;

--更新
declare
	v_person person_typ8;
begin
	select deref(perosn) into v_person from employee_tab8 where eno=1;
	v_person.address:='呼和浩特市神马路';
	update person_tab8 set address=v_person.address where name=v_person.name;
end;

--删除
begin
	delete from employee_tab8 where eno=1;
end;

Object Type的继承

9i新增,一个对象类型继承另一个对象类型。定义需要被继承的父类时需要指定not final,否则默认final,表示对象类型不能被继承。

1)建立对象类型person_typ9

create or replace type person_typ9 as object(
	name varchar2(10),
	gender varchar2(2),
	birthdate date,
	address varchar2(100),
	member function get_info return varchar2
) not final;    --注意not final


create or replace type body person_typ8 as
	member function get_info return varchar2 is
	begin
		return name||',0'||address;
	end;
end;

2)建立子对象类型

create or replace type employee_typ9 under person_typ9    --注意under person_typ9
(
	eno number(6),
	sal number(6,2),
	job varchar2(10),
	member function get_other return varchar2
);


create or replace type body employee_typ9 as
	member function get_other return varchar2 is
	begin
		return name||','||sal;
	end;
end;

3)建立行对象表

create table employee_tab9 of employee_typ9;
insert into person_tab8 values('马丽','女','11-1月-75','呼和浩特11号',1,1500,'图书管理员');
insert into person_tab8 values('王鸣','男','11-5月-75','呼和浩特21号',2,2000,'高级钳工');

4)查询

declare
	v_employee employee_typ9;
begin
	select value(a) into v_employee from employee_tab9 a where a.eno=1;
	dbms_output.put_line(v_employee.get_info||','||v_employee.get_other);
end;

维护Object Type

显示Object Type信息

select type_name, attributes, final from user_types;

增删Object Type的属性和方法

--增删Object Type的属性
alter type person_typ1 add attribute address varchar2(50) cascade;
alter type person_typ1 drop attribute birthdate cascade;
--cascade级联更新依赖对象类型的对象类型和对象表。
   
--增删Object Type的方法
alter type person_typ1 add member function getinfo return varchar2 cascade;
create or replace type body person_typ1 as
	member function get_info return varchar2 is
	begin
		return name||','||address;
	end;
end;

在动态SQL中使用对象

定义对象类型person_typ和数组类型hobbies_var,并创建包TEAMS

CREATE TYPE person_typ AS OBJECT (name VARCHAR2(25), age NUMBER);    --对象类型person_typ
 
CREATE TYPE hobbies_var AS VARRAY(10) OF VARCHAR2(25);    --数组类型hobbies_var
 
CREATE OR REPLACE PACKAGE teams    --TEAMS包定义                     
   AUTHID CURRENT_USER AS
   PROCEDURE create_table (tab_name VARCHAR2);
   PROCEDURE insert_row (tab_name VARCHAR2, p person_typ, h hobbies_var);
   PROCEDURE print_table (tab_name VARCHAR2);
END;
 
CREATE OR REPLACE PACKAGE BODY teams AS     --TEAMS包主体
   PROCEDURE create_table (tab_name VARCHAR2) IS
   BEGIN
      EXECUTE IMMEDIATE 'CREATE TABLE ' || tab_name ||
                        ' (pers person_typ, hobbs hobbies_var)';
   END;
   
   PROCEDURE insert_row (tab_name VARCHAR2, p person_typ, h hobbies_var) IS
   BEGIN
      EXECUTE IMMEDIATE 'INSERT INTO ' || tab_name ||
         				' VALUES (:1, :2)' USING p, h;
   END;
   
   PROCEDURE print_table (tab_name VARCHAR2) IS
      TYPE  refcurtyp IS REF CURSOR;
      v_cur refcurtyp;
      p     person_typ;
      h     hobbies_var;
   BEGIN
      OPEN v_cur FOR 'SELECT pers, hobbs FROM ' || tab_name;
      LOOP
         FETCH v_cur INTO p, h;
         EXIT WHEN v_cur%NOTFOUND;
         -- print attributes of 'p' and elements of 'h'
         DBMS_OUTPUT.PUT_LINE('Name: ' || p.name || ' - Age: ' || p.age);
         FOR i IN h.FIRST..h.LAST
         LOOP
           DBMS_OUTPUT.PUT_LINE('Hobby(' || i || '): ' || h(i));
         END LOOP;
      END LOOP;
      CLOSE v_cur;
   END;
END;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中可以使用关键字`return`来返回一个对象。如果方法的返回类型Object类型,那么可以返回任何类型对象。 例如,下面的代码演示了一个返回Object类型方法: ``` public Object getObject() { Object obj = new Object(); return obj; } ``` 在这个例子中,我们创建了一个Object类型对象,并将其返回。当我们调用这个方法时,它会返回一个新的Object对象。 如果你想修改已经存在的对象,你可以使用引用传递。这意味着你可以将一个对象引用作为参数传递给方法,并在方法内部修改对象的值。 例如,下面的代码演示了如何修改一个对象: ``` public class Person { private String name; public Person(String name) { this.name = name; } public void setName(String name) { this.name = name; } public String getName() { return name; } } ``` 在这个例子中,我们创建了一个Person类,它有一个属性name和一个方法setName()和getName()。在setName()方法中,我们可以修改name属性的值。 现在,我们可以创建一个Person对象,并将其引用传递给setName()方法,以修改对象的name属性。例如: ``` public static void main(String[] args) { Person person = new Person("Tom"); System.out.println(person.getName()); // 输出 "Tom" setName(person, "Jerry"); System.out.println(person.getName()); // 输出 "Jerry" } public static void setName(Person person, String name) { person.setName(name); } ``` 在这个例子中,我们创建了一个Person对象,并将其引用传递给setName()方法。在方法内部,我们调用了person对象的setName()方法,并将新的name值传递给它。这样,person对象的name属性就被修改了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值