在PL/SQL中,面向對象的程序設計師基於對象類型來完成的。對象類型是用戶自定義的一種復合數據類型,它封裝了數據結構和用於操縱這些數據結構的過程和函數。
數據庫的對象類型與JAVA和C#中德類相似,都可以包含屬性(用於存儲對象的狀態)和方法(用於建立對象的行為模型)。對象類型有時也為用戶自定義類型。
對象類型包括對象類型規范(Object Type Specification)和對象類型體(Object Type Body)兩個部分:
對象類型規范 對象與應用的接口,用於定義對象的公有屬性和方法。 對象類型體 用於實現對象類型規范所定義的公有方法。創建簡單數據類型的語法如下:
CREATE [OR REPLACE] TYPE type_name AS OBJECT(
column_name data_type
[,column_name data_type,...]
)
對象類型屬性用於描述對象所具有的特征,每個對象類型至少有一個屬性,至多包含1000個屬性。屬性類型可以是除以下類型外的任何Oracle數據類型(包括對象類型):LONG、LONG RAW、NCHAR、NCLOB、NVARCHAR2、ROWID、UROWID、以及PL/SQL的特定類型%TYPE和%ROWTYPE。
例1:
首先賦予用戶創建對象的權限:
GRANT CREATE ANY TYPE TO siege;
然後創建對象:
CREATE TYPE stu AS OBJECT(
name VARCHAR2(20),
sex VARCHAR2(2),
birthday DATE,
note VARCHAR2(300)
)
我們也可以將一個對象當作一個普通類型來使用:
CREATE TYPE stu2 AS OBJECT(
sid NUMBER(4),
student stu
)
同樣,我們可以在創建表的時候使用自定義的類型:
CREATE TABLE student2(
sid NUMBER(4),
student stu
)
創建帶有函數的對象類型語法如下:
CREATE [OR REPLACE] TYPE type_name AS OBJECT(
column_name data_type
[,column_name data_type,...],
member function method_name(args_list) return_type,
...
)
其中,function表示一個函數,創建對象類型的member語句中,也可以使用member procedure代替member function,只不過不再有返回值。
如果對象中帶有函數,還需要聲明一個對象體(BODY),對象體定義了函數的實際代碼,其創建語法如下:
CREATE [OR REPLACE] TYPE BODY type_name AS
MEMBER FUNCTION method_name RETURN return_type {AS|IS}
variable declareations...;
BEGIN ...
RETURN return_value;
END;
END;
column_name data_type
[,column_name data_type,...]
例2:
首先創建對象類型:
CREATE TYPE stu3 AS OBJECT(
name VARCHAR2(20),
sex VARCHAR2(2),
birthday DATE,
note VARCHAR2(300),
MEMBER FUNCTION get_age RETURN NUMBER
)
然後創建對象體:
CREATE TYPE BODY stu3 AS
MEMBER FUNCTION get_age RETURN NUMBER AS
v_months NUMBER;
BEGIN
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,birthday)/12) INTO
v_months FROM dual;
RETURN v_months;
END;
END;
然後我們創建student3表:
CREATE TABLE student3(
sid NUMBER(4),
student stu3
)
現在插入一條數據:
INSERT INTO student3 VALUES(1,stu3('siege','M',TO_DATE('19910228','YYYYMMDD'),'my notes'));
現在我們查詢剛才插入的語句:
SELECT s.sid,s.student.name,s.student.sex,s.student.birthday,s.student.note,s.student.get_age() FROM student3 s
其結果如下:
SID STUDENT.NAME STUDENT.SEX STUDENT.BIRTHDAY STUDENT.NOTE S.STUDENT.GET_AGE()
1 siege M 28/02/1991 my notes 24
在使用對象類型之前,需要明確對象類型的結構(主要包括屬性的數據類型和數據范圍),查看對象的結構可以使用DESCRIBE命令。
在PL/SQL developer的command window打開一個窗口,輸入如下語句來設置信息深度:
SET DESCRIBE [DEPTH {1|n|ALL}]
深度的取值范圍為1-50,默認值為1。深度表示對象的層次,類似JAVA中包的層次,本例中STU2的深度為2
DESCRIBE STU2;
即可查詢對象類型的信息了。
列對象(COLUMN OBJECT)使用對象類類型定義單個的列,存儲在此列中的對象成為列對象。
如果只需要使用對象類型來定義表中的單個列,可以使用列對象的形式。使用列對象的方式是在創建表時,將列的數據類型定義為對象類型。
語法如下:
column_name type_name
向包含列對象的表中添加數據時,必須使用構造函數為列對象提供屬性值。
對象表(OBJECT TABLE)使用對象類型定義表中的一整行,此表被稱為對象表。
如果需要使用對象類型來定義整個表,那麼可以將整個表創建為對象表。使用OF子句將表標識為對象表,其語法如下:
CREATE TABLE table_name OF type_name;
向對象表中添加紀錄時,可以有以下兩種方式:
通過構造函數提供屬性值
在關系表中提供列值
例3:
CREATE TABLE student4 OF stu;
此時就創建好了對象表student4 。
通過構造函數向表中添加數據:
INSERT INTO student4 VALUES(stu('siege','M',TO_DATE('19910228','YYYYMMDD'),'NOTHING'));
通過向普通表中添加數據的方法:
INSERT INTO student4 VALUES('cage','M',TO_DATE('19910228','YYYYMMDD'),'NOTHING')
對象表的查詢除了可以使用一般的查詢語句,還可以使用value函數:
SELECT value(s) FROM student4 s
也可以單獨查詢某一列或幾列:
SELECT VALUE(s).sex FROM student4 s
對象表中的每個對象都具有惟一的對象標識符(OBJECT IDENTIFIER,OID),它可以存儲在名稱為REF的列中。對象引用使用REF類型進行定義,通常都可以用作指向對象表中對象的指針,可以使用對象引用為對象表之間的關系建立模型,而不是使用外鍵。
使用REF()函數來檢索對象的OID。
例4:
SELECT REF(s) FROM student4 s
其結果:
REF(S)
000028020928DFC3EBA9874580B244E5CDEBF8F899401875D0C7E041528E5969734EB8E5B5014000F50000
0000280209AFF154978FF84383BAFDD806C52FD6F3401875D0C7E041528E5969734EB8E5B5014000F50001
這一長串數字和字母的組合就是OID,它標識數據庫中對象的位置。可以將OID存儲在一個對象引用中,通過它就可以訪問它引用的對象。
可以使用對象引用為對象表之間的關系建立模型。使用REF類型來定義一個對象引用。語法如下:
CREATE TABLE table_name(
ref_name REF type_name SCOPE IS table_type_name
);
其中,SCOPE IS子句將對象引用限制在特定表中的對象上。
例5:
CREATE TABLE student_object_ref(
ID NUMBER(4),
stu_ref REF stu SCOPE IS student4
)
插入兩條數據:
INSERT INTO student_object_ref(id,stu_ref) VALUES
(1,(SELECT REF(s) FROM student4 s WHERE s.name='siege'));
INSERT INTO student_object_ref(id,stu_ref) VALUES
(2,(SELECT REF(s) FROM student4 s WHERE s.name='cage'))
查詢結果:
ID STU_REF
1 000022020828DFC3EBA9874580B244E5CDEBF8F899401875D0C7E041528E5969734EB8E5B5
2 0000220208AFF154978FF84383BAFDD806C52FD6F3401875D0C7E041528E5969734EB8E5B5
現在我們通過DEREF函數來查詢結果:
SELECT DEREF(stu_ref) FROM student_object_ref
其結果如下:
DEREF(STU_REF).NAME DEREF(STU_REF).SEX DEREF(STU_REF).BIRTHDAY DEREF(STU_REF).NOTE
siege M 28/02/1991 NOTHING
cage M 28/02/1991 NOTHING
此時不再顯示標識符,而是對象引用對應的數據。我們可以通過對象引用來進行數據查詢:
SELECT id,DEREF(stu_ref).name,DEREF(stu_ref).sex,DEREF(stu_ref).note FROM student_object_ref
我們也可以對對象引用進行更改:
UPDATE student_object_ref SET stu_ref=(SELECT REF(s) FROM student4 s WHERE s.name='cage')