PL/SQL物件導向


在本章中,我們將討論物件導向的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方法是一個函式,它的值取決於屬性的值。 例如,對於客戶物件,如果客戶程式碼對於兩個客戶是相同的,則兩個客戶可以是相同的。 所以這兩個物件之間的關係將取決於程式碼的值。

排序方法

排序方法實現了一些用於比較兩個物件的內部邏輯。例如,對於一個矩形物件,如果矩形的兩邊都較大,則矩形比另一個矩形大。

使用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物件的繼承

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

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提示符下執行時,它會產生以下結果 -

型別已建立。