PL/SQL面向对象 - PL/SQL教程

PL/SQL允许定义一个对象类型,这有助于在Oracle的数据库中设计的面向对象。对象类型可以包装复合类型。使用对象允许实现数据的具体结构现实世界中的对象和方法操作它。对象有属性和方法。属性是一个对象的属性,并用于存储对象的状态;和方法被用于模拟其行为。

使用CREATE[OR REPLACE] TYPE语句中创建的对象。下面是一个例子,创建包含一些属性的简单的地址对象:

CREATE OR REPLACE TYPE address AS OBJECT
(house_no varchar2(10),
 street varchar2(30),
 city varchar2(20),
 state varchar2(10),
 pincode varchar2(10)
);
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Type created.

让我们来创建一个多个客户对象,包装的属性和方法,拥有面向对象的感觉:

CREATE OR REPLACE TYPE customer AS OBJECT
(code number(5),
 name varchar2(30),
 contact_no varchar2(12),
 addr address,
 member procedure display
);
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Type created.

实例化对象

定义对象类型提供了一个蓝图对象。要使用这个对象,需要创建这个对象的实例。可以访问属性,使用实例名称和接入操作符,如下对象的方法(.):

DECLARE
   residence address;
BEGIN
   residence := address('103A', 'M.G.Road', 'Jaipur', 'Rajasthan','201301');
   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('State: '|| residence.state);
   dbms_output.put_line('Pincode: '|| residence.pincode);
END;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

House No: 103A
Street: M.G.Road
City: Jaipur
State: Rajasthan
Pincode: 201301

PL/SQL procedure successfully completed.

成员方法

成员方法是用于操纵对象属性。提供的成员方法的声明,同时声明的对象类型。对象主体限定的代码成员方法。使用CREATE TYPE BODY语句创建的对象体。

构造函数返回一个新的对象作为其值的功能。每个对象都有一个系统定义的构造方法。构造方法的名称是相同的对象类型。例如:

residence := address('103A', 'M.G.Road', 'Jaipur', 'Rajasthan','201301');

比较方法被用于比较的对象。有两种方法来比较对象:

  • 映射方法:映射方法它的值取决于属性的值,以这样的方式实现函数。例如,一个客户对象,如果客户代码是相同的两个客户,可以认为是相同的一个。所以这两个对象之间的关系将取决于代码的值。

  • 顺序方法:顺序方法实现一些内部逻辑比较两个对象。例如,对于矩形(rectangle)对象,如果其两侧都大,则表示矩形(rectangle)大于另一个矩形(rectangle)。

使用映射方法

让我们试着去了解上面使用下面的矩形对象的概念:

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提示符执行时,它产生了以下结果:

Type created.

创建类型体:

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;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Type body created.

现在,使用矩形(rectangle)对象及其成员函数:

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;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Length: 8
Width: 9
Length: 5
Width: 7

PL/SQL procedure successfully completed.

使用顺序的方法

现在,相同的效果可以使用顺序方法来实现。让我们用一个顺序方法重新创建矩形(rectangle)对象:

CREATE OR REPLACE TYPE rectangle AS OBJECT
(length number,
 width number,
 member procedure display,
 order member function measure(r rectangle) return number
);
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Type created.

创建型类体:

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;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Type body created.

使用矩形(rectangle)对象及其成员函数:

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;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Length: 23
Width: 44
Length: 15
Width: 17
Length: 23
Width: 44

PL/SQL procedure successfully completed.

继承PL/SQL对象:

PL/SQL允许从现有的基础对象创建对象。为了实现继承,基本对象应被声明为NOT FINAL。默认值是FINAL。

下面的程序说明了继承PL/SQL对象。让我们创建一个名为TableTop,这是从Rectangle对象继承。另一个对象是由基本矩形(rectangle)对象创建:

CREATE OR REPLACE TYPE rectangle AS OBJECT
(length number,
 width number,
 member function enlarge( inc number) return rectangle,
 NOT FINAL member procedure display) NOT FINAL
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Type created.

创建基本类型主体:

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;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Type body created.

创建 tabletop 子对象:

CREATE OR REPLACE TYPE tabletop UNDER rectangle
(  
   material varchar2(20);
   OVERRIDING member procedure display
)
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Type created.

创造型体的 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;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Type body created.

使用 tabletop 对象及其成员函数:

DECLARE
   t1 tabletop;
   t2 tabletop;
BEGIN
   t1:= tabletop(20, 10, 'Wood');
   t2 := tabletop(50, 30, 'Steel');
   t1.display;
   t2.display;
END;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Length: 20
Width: 10
Material: Wood
Length: 50
Width: 30
Material: Steel

PL/SQL procedure successfully completed.

PL/SQL抽象对象

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提示符执行时,它产生了以下结果:

Type created.