首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Oracle 物件導向開發入門:物件型別、實例、儲存模式 (Object Column vs Object Table) 與比較方法

     編輯:Oracle 資料庫相關知識

核心概念

Oracle 8i+ 引入物件導向特性:封裝 (資料與方法結合)、繼承 (型別層次)、多型 (執行期動態綁定)。物件型別 = 類別,物件實例 = 物件。

兩步驟定義物件

步驟 1:建立物件型別規格

CREATE OR REPLACE TYPE emp_obj AS OBJECT (
  emp_id    NUMBER,
  emp_name  VARCHAR2(50),
  salary    NUMBER,
  -- Member Function (方法)
  MEMBER FUNCTION get_annual_sal RETURN NUMBER,
  -- Map Method (用於比較/排序)
  MAP MEMBER FUNCTION get_id RETURN NUMBER
);
/
CREATE OR REPLACE TYPE BODY emp_obj AS
  MEMBER FUNCTION get_annual_sal RETURN NUMBER IS
  BEGIN
    RETURN self.salary * 12;
  END;
  
  MAP MEMBER FUNCTION get_id RETURN NUMBER IS
  BEGIN
    RETURN self.emp_id;
  END;
END;
/

步驟 2:宣告/建立物件實例

-- PL/SQL 區塊中宣告區域變數
DECLARE
  v_emp emp_obj := emp_obj(1001, 'Alice', 50000); -- 建構式初始化
BEGIN
  DBMS_OUTPUT.PUT_LINE(v_emp.emp_name || ' 年薪: ' || v_emp.get_annual_sal);
END;
/
-- 或建立表儲存物件 (見下節)

物件在資料庫中的兩種儲存模式

模式一:物件欄位 - 關聯表中的複雜屬性

CREATE TABLE departments (
  dept_id   NUMBER PRIMARY KEY,
  dept_name VARCHAR2(100),
  manager   emp_obj  -- 物件欄位
);

INSERT INTO departments VALUES (
  10, 'IT', emp_obj(1001, 'Alice', 50000)
);

-- 查詢物件屬性
SELECT d.dept_name, d.manager.emp_name, d.manager.get_annual_sal()
FROM departments d;

模式二:物件表 - 每列即一個物件

CREATE TABLE employees_obj OF emp_obj (
  PRIMARY KEY (emp_id)
);

INSERT INTO employees_obj VALUES (emp_obj(1001, 'Alice', 50000));
INSERT INTO employees_obj VALUES (emp_obj(1002, 'Bob', 60000));

-- 物件表查詢
SELECT VALUE(e) FROM employees_obj e WHERE e.emp_id = 1001;
-- VALUE(e) 回傳完整物件實例

關鍵差異對照

特性物件欄位物件表
定義方式一般表欄位型別為物件型別CREATE TABLE ... OF type
儲存結構扁平化展開為欄位 (隱含欄位)每屬性一欄,含系統產生 OID
方法儲存不儲存方法程式碼不儲存方法程式碼
參考/導航需 Join 父表支援 REF、DEREF 導航
索引可建立 Function-Based Index可直接對屬性建立索引

物件比較與排序:MAP vs ORDER

  • MAP MEMBER FUNCTION:回傳標量值 (NUMBER/DATE/VARCHAR2),Oracle 自動用此值比較大小、排序、DISTINCT、GROUP BY。效能較好。
  • ORDER MEMBER FUNCTION:接受另一物件參數,回傳負/零/正 (如 self.attr - other.attr)。適用複雜比較邏輯。
  • 一個型別只能定義一個 MAP 或 ORDER 方法。

型別繼承與多型 (9i+)

-- 父型別
CREATE TYPE person_obj AS OBJECT (
  name VARCHAR2(50),
  MEMBER PROCEDURE print
) NOT FINAL; -- 允許被繼承
/
CREATE TYPE BODY person_obj AS
  MEMBER PROCEDURE print IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('Person: ' || name);
  END;
END;
/

-- 子型別
CREATE TYPE student_obj UNDER person_obj (
  student_id NUMBER,
  OVERRIDING MEMBER PROCEDURE print -- 覆寫
);
/
CREATE TYPE BODY student_obj AS
  OVERRIDING MEMBER PROCEDURE print IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('Student: ' || name || ' ID: ' || student_id);
  END;
END;
/

-- 多型展示
DECLARE
  p person_obj := person_obj('John');
  s student_obj := student_obj('Mary', 2024001);
BEGIN
  p.print(); -- Person: John
  s.print(); -- Student: Mary ID: 2024001
  -- 多型指派
  p := s;    -- 子型別指派給父型別變數
  p.print(); -- Student: Mary ID: 2024001 (動態綁定)
END;

實務應用場景

  1. 複雜資料結構封裝:地址 (國家、城市、街道、郵碼) 定義為 ADDRESS_OBJ,多表共用。
  2. 空間/多媒體資料:SDO_GEOMETRY、ORDSYS.ORDAUDIO 皆為內建物件型別。
  3. PL/SQL API 設計:以物件型別封裝輸入/輸出參數,減少參數個數、提升可讀性。
  4. 型別演進:ALTER TYPE ... ADD ATTRIBUTE、REPLACE TYPE BODY 支援版本演進。

結語

Oracle 物件導向特性將資料與行為封裝於資料庫層,配合 MAP/ORDER 比較、型別繼承多型、REF 導航,能優雅處理複雜業務模型。掌握 CREATE TYPE、物件欄位 vs 物件表選型、建構式初始化,是進階 PL/SQL 開發者的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved