PL/SQL允许定义一个对象类型,这有助于在Oracle的数据库中设计的面向对象。对象类型可以包装复合类型。
创建对象:
CREATE OR REPLACE TYPE objName AS OBJECT
(
--定义对象类型属性
var1 type,
var2 type,
var3 type,
...
-- 定义对象的成员方法,可以访问对象本身的属性
MEMBER FUNCTION fun_name1[(参数名 数据类型[,...])] return return_type,
MEMBER PROCEDURE proc_name1[(参数名 数据类型[,...])]
--静态方法,不能访问对象本身的属性,只能访问静态数据
STATIC FUNCTION fun_name2[(参数名 数据类型[,...])] return return_type,
STATIC PROCEDURE proc_name2[(参数名 数据类型[,...])]
);
创建类型体:
CREATE OR REPLACE TYPE BODY objName AS
-- 实现对象成员方法
MEMBER FUNCTION fun_name1[(参数名 数据类型[,...])]
RETURN return_type
AS
BEGIN
<function_body>
END fun_name1;
MEMBER proc_name1[(参数名 数据类型[,...])]
AS
BEGIN
<procedure_body>
END proc_name1;
STATIC FUNCTION fun_name2[(参数名 数据类型[,...])]
RETURN return_type
AS
BEGIN
<function_body>
END fun_name2;
STATIC proc_name2[(参数名 数据类型[,...])]
AS
BEGIN
<procedure_body>
END proc_name2;
END;
实例化对象:
要使用这个对象,需要创建这个对象的实例。每个对象都有一个系统定义的构造方法,构造方法的名称是相同的对象类型。
DECLARE
residence objName; -- 定义对象类型
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);
END;
/
比较方法
比较方法被用于比较的对象。有两种方法来比较对象:
- 映射方法:将对象实例映射为标量数值(NUMBER,DATE,VARCHAR2等),然后根据该标量类型数据可以排序对象实例。例如,一个客户对象,如果两个客户代码是相同的,可以认为是相同的一个。所以这两个对象之间的关系将取决于代码的值。
- 顺序方法:实现一些内部逻辑比较两个对象。
- 一个对象类型最多只能定义一个MAP/ORDER方法,并且MAP方法和ORDER方法不能同时使用。
- MAP方法可以在多个对象实例之间进行排序,而ORDER方法只能比较两个对象实例的大小
(1)映射方法
CREATE OR REPLACE TYPE book_obj AS OBJECT (
isbn CHAR (10),
title VARCHAR2 (100),
num_pages NUMBER,
MAP MEMBER FUNCTION return_isbn RETURN CHAR
);
CREATE OR REPLACE TYPE BODY book_obj
AS
MAP MEMBER FUNCTION return_isbn RETURN CHAR AS
BEGIN
RETURN SELF.isbn;
END return_isbn;
END;
--现在就可以通过isdn来比较两个对象
DECLARE
v_book1 book := book ('72121203', 'Oracle DBA 101', 563);
v_book2 book := book ('72122048', 'Oracle 8i: A Beginner''s Guide', 765);
BEGIN
IF v_book1 < v_book2 THEN
DBMS_OUTPUT.put_line (v_book1.title || ' < ' || v_book2.title);
ELSIF v_book1 = v_book2 THEN
DBMS_OUTPUT.put_line (v_book1.title || ' = ' || v_book2.title);
ELSE
DBMS_OUTPUT.put_line (v_book1.title || ' > ' || v_book2.title);
END IF;
END;
(2)使用顺序的方法
现在,相同的效果可以使用顺序方法来实现。
CREATE OR REPLACE TYPE book_obj AS OBJECT (
isbn CHAR (10),
title VARCHAR2 (100),
num_pages NUMBER,
ORDER MEMBER FUNCTION compare_book (p_isbn IN BOOK_OBJ) RETURN CHAR
);
CREATE OR REPLACE TYPE BODY book_obj
AS
ORDER MEMBER FUNCTION compare_book (p_isbn IN BOOK_OBJ) RETURN NUMBER AS
BEGIN
IF p_isbn.isbn < SELF.isbn THEN
RETURN 1;
ELSIF p_isbn.isbn > SELF.isbn THEN
RETURN -1;
ELSE
RETURN 0;
END IF;
END compare_book;
END;
DECLARE
v_book1 book := book ('72121203', 'Oracle DBA 101', 563);
v_book2 book := book ('72122048', 'Oracle 8i: A Beginner''s Guide', 765);
BEGIN
IF v_book1 < v_book2 THEN
DBMS_OUTPUT.put_line (v_book1.title || ' < ' || v_book2.title);
ELSIF v_book1 = v_book2 THEN
DBMS_OUTPUT.put_line (v_book1.title || ' = ' || v_book2.title);
ELSE
DBMS_OUTPUT.put_line (v_book1.title || ' > ' || v_book2.title);
END IF;
END;
继承PL/SQL对象
PL/SQL允许从现有的基础对象创建对象。为了实现继承,基本对象应被声明为NOT FINAL。默认值是FINAL。
基础对象:
CREATE OR REPLACE TYPE baseObj AS OBJECT
(
var1 type,
var2 type,
MEMBER FUNCTION fu_name[(参数名 数据类型[,...])] return reu_type
)NOT FINAL; --指定该类可以被继承,如果指定FINAL,表示该类无法被继承
子类对象:
CREATE OR REPLACE TYPE subObj UNDER baseObj
(
v1 type,
v2 type,
-- 声明重写父类方法
OVERRIDING MEMBER FUNCTION fu_name[(参数名 数据类型[,...])]
)