在本章中,我们将讨论面向对象的pl/sql。 pl/sql允许定义一个对象类型,这有助于在oracle中设计面向对象的数据库。 对象类型允许创建复合类型。使用对象可实现具有特定数据结构的真实世界对象以及操作它的方法。对象具有属性和方法。对象的属性用于存储对象的状态; 并使用方法来建模其行为。
对象是使用create [or replace] type
语句创建的。 以下是创建一个由几个属性组成的简单地址(address
)对象的例子 -
create or replace type address as object
(
house_no varchar2(10),
street varchar2(30),
city varchar2(20),
state varchar2(10),
pincode varchar2(10)
);
/
当上面的代码在sql提示符下执行时,它会产生以下结果 -
类型已创建。
下面再创建另一个对象:customer
,将属性和方法包装在一起,以具有面向对象的感觉 -
create or replace type customer as object
(
code number(5),
name varchar2(30),
contact_no varchar2(12),
addr address,
member procedure display
);
/
当上面的代码在sql提示符下执行时,它会产生以下结果 -
类型已创建。
定义对象类型为对象提供模板(或蓝图)。要使用这个对象,需要创建这个对象的实例。可以使用实例名称和访问运算符(.
)来访问对象的属性和方法,如下所示 -
set serveroutput on size 9999;
declare
residence address;
begin
residence := address('1502a', '人民大道', '海口', '海南','201901');
dbms_output.put_line('house no: '|| residence.house_no);
dbms_output.put_line('street: '|| residence.street);
dbms_output.put_line('city: '|| residence.city);
dbms_output.put_line('province: '|| residence.state);
dbms_output.put_line('pincode: '|| residence.pincode);
end;
/
执行上面示例代码,得到以下结果 -
成员方法用于操作对象的属性。在声明对象类型的同时提供成员方法的声明。 对象体定义了成员方法的代码。对象正文是使用create type body
语句创建的。
构造函数是返回一个新对象作为其值的函数。每个对象都有一个系统定义的构造方法。构造函数的名称与对象类型相同。 例如 -
residence := address('1502a', '人民大道', '海口', '海南','201901');
比较方法用于比较对象。 有两种方法来比较对象 -
映射方法
map
方法是一个函数,它的值取决于属性的值。 例如,对于客户对象,如果客户代码对于两个客户是相同的,则两个客户可以是相同的。 所以这两个对象之间的关系将取决于代码的值。
排序方法
排序方法实现了一些用于比较两个对象的内部逻辑。例如,对于一个矩形对象,如果矩形的两边都较大,则矩形比另一个矩形大。
下面尝试使用以下矩形对象来了解上述概念 -
set serveroutput on size 999999;
create or replace type rectangle as object
(
length number,
width number,
member function enlarge( inc number) return rectangle,
member procedure display,
map member function measure return number
);
/
当上面的代码在sql提示符下执行时,它会产生以下结果 -
类型已创建。
接下来,创建类型主体 -
create or replace type body rectangle as
member function enlarge(inc number) return rectangle is
begin
return rectangle(self.length + inc, self.width + inc);
end enlarge;
member procedure display is
begin
dbms_output.put_line('length: '|| length);
dbms_output.put_line('width: '|| width);
end display;
map member function measure return number is
begin
return (sqrt(length*length + width*width));
end measure;
end;
/
执行上面示例代码,得到以下输出结果 -
类型主体已创建。
现在使用矩形对象及其成员函数 -
set serveroutput on size 99999;
declare
r1 rectangle;
r2 rectangle;
r3 rectangle;
inc_factor number := 5;
begin
r1 := rectangle(3, 4);
r2 := rectangle(5, 7);
r3 := r1.enlarge(inc_factor);
r3.display;
if (r1 > r2) then -- calling measure function
r1.display;
else
r2.display;
end if;
end;
/
执行上面示例代码,得到以下输出结果 -
现在,使用排序方法可以达到同样的效果。下面来看看如使用排序方法重新创建矩形对象 -
create or replace type rectangle as object
(
length number,
width number,
member procedure display,
order member function measure(r rectangle) return number
);
/
当上面的代码在sql提示符下执行时,它会产生以下结果 -
类型已创建。
创建类型主体 -
create or replace type body rectangle as
member procedure display is
begin
dbms_output.put_line('length: '|| length);
dbms_output.put_line('width: '|| width);
end display;
order member function measure(r rectangle) return number is
begin
if(sqrt(self.length*self.length + self.width*self.width)>
sqrt(r.length*r.length + r.width*r.width)) then
return(1);
else
return(-1);
end if;
end measure;
end;
/
执行上面示例代码,得到以下结果 -
类型主体已创建。
使用矩形对象及其成员函数 -
set serveroutput on size 99999;
declare
r1 rectangle;
r2 rectangle;
begin
r1 := rectangle(23, 44);
r2 := rectangle(15, 17);
r1.display;
r2.display;
if (r1 > r2) then -- calling measure function
r1.display;
else
r2.display;
end if;
end;
/
执行上面示例代码,得到以下结果 -
pl/sql允许从现有的基础对象创建对象。为了实现继承,基类对象应该声明为not final
。默认是final
。
以下程序演示了pl/sql对象中的继承。首先创建另一个名为tabletop
对象,它是从rectangle
对象继承的。因此,需要创建这个基础的rectangle
对象,参考以下代码 -
create or replace type rectangle force as object
(
length number,
width number,
member function enlarge( inc number) return rectangle,
not final member procedure display) not final
/
执行上面示例代码,得到以下结果 -
类型已创建。
创建基本类型的主体 -
create or replace type body rectangle as
member function enlarge(inc number) return rectangle is
begin
return rectangle(self.length + inc, self.width + inc);
end enlarge;
member procedure display is
begin
dbms_output.put_line('length: '|| length);
dbms_output.put_line('width: '|| width);
end display;
end;
/
执行上面示例代码,得到以下结果 -
类型主体已创建。
创建子对象tabletop -
create or replace type tabletop under rectangle
(
material varchar2(20),
overriding member procedure display
)
/
执行上面示例代码,得到以下结果 -
类型已创建。
为子对象tabletop
创建类型主体 -
create or replace type body tabletop as
overriding member procedure display is
begin
dbms_output.put_line('length: '|| length);
dbms_output.put_line('width: '|| width);
dbms_output.put_line('material: '|| material);
end display;
/
执行上面示例代码,得到以下结果 -
类型主体已创建。
使用tabletop
对象及其成员函数 -
declare
t1 tabletop;
t2 tabletop;
begin
t1:= tabletop(20, 10, 'wood');
t2 := tabletop(50, 30, 'steel');
t1.display;
t2.display;
end;
/
当执行上面示例代码时,得到以下结果 -
length: 20
width: 10
material: wood
length: 50
width: 30
material: steel
not instantiable
子句用来声明一个抽象对象。不能直接使用抽象对象, 必须创建抽象对象的子类型或子类型才能使用它的功能。
例如,
create or replace type rectangle as object
(length number,
width number,
not instantiable not final member procedure display)
not instantiable not final
/
当上面的代码在sql提示符下执行时,它会产生以下结果 -
类型已创建。