全部產品
Search
文件中心

PolarDB:建立物件類型

更新時間:Dec 21, 2024

您可以使用CREATE TYPE命令建立物件類型規格,並可以使用CREATE TYPE BODY命令建立物件類型主體。本節提供一些如何使用CREATE TYPE和CREATE TYPE BODY命令的樣本。

第一個樣本建立addr_object_type物件類型,其中只包含屬性,不包含方法:

CREATE OR REPLACE TYPE addr_object_type AS OBJECT (
    street          VARCHAR2(30),
    city            VARCHAR2(20),
    state           CHAR(2),
    zip             NUMBER(5)
);

由於此物件類型中不存在方法,因此不需要物件類型主體。此樣本建立了一個複合類型,使您可以將相關對象視為單個屬性。

成員方法

成員方法是在某一物件類型中定義的函數或預存程序,只能通過該類型的執行個體進行調用。成員方法可訪問它們運行所在的對象執行個體的屬性,並且可更改這些屬性。

以下物件類型規格建立emp_obj_typ物件類型:

CREATE OR REPLACE TYPE emp_obj_typ AS OBJECT (
    empno           NUMBER(4),
    ename           VARCHAR2(20),
    addr            addr_object_type,
    MEMBER PROCEDURE display_emp(SELF IN OUT emp_obj_typ)
);

物件類型emp_obj_typ包含一個名為display_emp的成員方法。display_emp使用SELF參數,後者傳遞調用該方法的對象執行個體。

SELF參數的資料類型是所定義的物件類型的資料類型。SELF始終引用調用方法的執行個體。SELF參數是成員預存程序或函數中的第一個參數,無論它是否在參數列表中明確聲明。

以下程式碼片段為emp_obj_typ定義物件類型主體:

CREATE OR REPLACE TYPE BODY emp_obj_typ AS
    MEMBER PROCEDURE display_emp (SELF IN OUT emp_obj_typ)
    IS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Employee No   : ' || empno);
        DBMS_OUTPUT.PUT_LINE('Name          : ' || ename);
        DBMS_OUTPUT.PUT_LINE('Street        : ' || addr.street);
        DBMS_OUTPUT.PUT_LINE('City/State/Zip: ' || addr.city || ', ' ||
            addr.state || ' ' || LPAD(addr.zip,5,'0'));
    END;
END;

您也可以在物件類型主體中使用SELF參數。為闡釋如何在CREATE TYPE BODY命令中使用SELF參數,上述物件類型主體可按如下所示編寫:

CREATE OR REPLACE TYPE BODY emp_obj_typ AS
    MEMBER PROCEDURE display_emp (SELF IN OUT emp_obj_typ)
    IS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Employee No   : ' || SELF.empno);
        DBMS_OUTPUT.PUT_LINE('Name          : ' || SELF.ename);
        DBMS_OUTPUT.PUT_LINE('Street        : ' || SELF.addr.street);
        DBMS_OUTPUT.PUT_LINE('City/State/Zip: ' || SELF.addr.city || ', ' ||
            SELF.addr.state || ' ' || LPAD(SELF.addr.zip,5,'0'));
    END;
END;

這兩個版本的emp_obj_typ主體完全相同。

靜態方法

與成員方法一樣,靜態方法也屬於某一類型。但是靜態方法不是由類型的執行個體進行調用,而是通過使用類型的名稱進行調用。例如,要調用 emp_obj_type 類型中定義的名為 get_count 的靜態函數,您將編寫以下語句:

emp_obj_type.get_count();

靜態方法無權訪問對象執行個體的屬性,也不能更改這些屬性,並且通常不使用類型的執行個體。

以下物件類型規格包含靜態函數get_dname和成員預存程序display_dept:

CREATE OR REPLACE TYPE dept_obj_typ AS OBJECT (
    deptno          NUMBER(2),
    STATIC FUNCTION get_dname(p_deptno IN NUMBER) RETURN VARCHAR2,
    MEMBER PROCEDURE display_dept
);

dept_obj_typ的物件類型主體定義一個名為get_dname的靜態函數和一個名為display_dept的成員預存程序:

CREATE OR REPLACE TYPE BODY dept_obj_typ AS
    STATIC FUNCTION get_dname(p_deptno IN NUMBER) RETURN VARCHAR2
    IS
        v_dname     VARCHAR2(14);
    BEGIN
        CASE p_deptno
            WHEN 10 THEN v_dname := 'ACCOUNTING';
            WHEN 20 THEN v_dname := 'RESEARCH';
            WHEN 30 THEN v_dname := 'SALES';
            WHEN 40 THEN v_dname := 'OPERATIONS';
            ELSE v_dname := 'UNKNOWN';
        END CASE;
        RETURN v_dname;
    END;
    MEMBER PROCEDURE display_dept
    IS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Dept No    : ' || SELF.deptno);
        DBMS_OUTPUT.PUT_LINE('Dept Name  : ' ||
            dept_obj_typ.get_dname(SELF.deptno));
    END;
END;

在靜態函數get_dname中,不能有對SELF的引用。由於靜態函數的調用獨立於任何對象執行個體,因此沒有對任何對象屬性的隱式訪問權。

成員預存程序display_dept可以訪問SELF參數中傳遞的對象執行個體的deptno屬性。不必在display_dept參數列表中明確聲明SELF參數。

display_dept預存程序中的最後一個DBMS_OUTPUT.PUT_LINE語句包含對靜態函數get_dname(由其物件類型名稱dept_obj_typ限定)的調用。

建構函式方法

建構函式方法是一個函數,該函數通過為對象的成員分配值來建立物件類型的執行個體。物件類型可以定義多個建構函式來完成不同的任務。建構函式方法是一個成員函數(通過SELF參數進行調用),其名稱與類型的名稱相匹配。

例如,如果定義名為address的類型,則每個建構函式也名為address。通過建立一個或多個同名但參數類型不同的不同建構函式,可以重載建構函式。

SPL編譯器將為每個物件類型提供預設建構函式。預設建構函式是一個成員函數,其名稱與類型的名稱匹配,並且其參數列表與類型成員也匹配(按順序)。例如,給出如下物件類型:

CREATE TYPE address AS OBJECT
(
  street_address VARCHAR2(40),
  postal_code    VARCHAR2(10),
  city           VARCHAR2(40),
  state          VARCHAR2(2)
)

SPL 編譯器將提供具有以下特徵的預設建構函式:

CONSTRUCTOR FUNCTION address
(
  street_address VARCHAR2(40),
  postal_code    VARCHAR2(10),
  city           VARCHAR2(40),
  state          VARCHAR2(2)
)

預設建構函式的主體只是將每個成員設定為NULL。

要建立自訂建構函式,請在CREATE TYPE中聲明該建構函式(使用關鍵字constructor),然後在CREATE TYPE BODY命令中定義該建構函式。例如,您可能希望為address類型建立一個自訂建構函式,它在給出street_address和postal_code時計算城市和州。

CREATE TYPE address AS OBJECT
(
  street_address VARCHAR2(40),
  postal_code    VARCHAR2(10),
  city           VARCHAR2(40),
  state          VARCHAR2(2),

  CONSTRUCTOR FUNCTION address
   (
     street_address VARCHAR2,
     postal_code VARCHAR2
    ) RETURN self AS RESULT
);

CREATE TYPE BODY address AS
  CONSTRUCTOR FUNCTION address
   (
     street_address VARCHAR2,
     postal_code VARCHAR2
    ) RETURN self AS RESULT
  IS
    BEGIN
      self.street_address := street_address;
      self.postal_code := postal_code;
      self.city := postal_code_to_city(postal_code);
      self.state := postal_code_to_state(postal_code);
      RETURN;
    END;
END;

要建立物件類型的執行個體,將調用該類型的某一建構函式方法。例如:

DECLARE
  cust_addr address := address('100 Main Street', '02203');
BEGIN
  DBMS_OUTPUT.PUT_LINE(cust_addr.city);  -- displays Boston
  DBMS_OUTPUT.PUT_LINE(cust_addr.state); -- displays MA
END;

自訂建構函式通常用於在給定的資訊不完整時導出成員值。上一樣本在給出郵遞區號時計算city和state的值。

自訂建構函式還用於強制執行限制對象狀態的商務規則。例如,如果定義一個物件類型來代表payment,您可以使用自訂建構函式確保不能建立amount為NULL、負數或零的payment類型的對象。預設建構函式將payment.amount設定為NULL,因此您必須建立一個自訂建構函式(其特徵與預設建構函式相匹配)來禁止金額為NULL。