DM 類資料型別

eric0435發表於2020-03-18

類型別
DM7透過類型別在DMSQL程式中實現物件導向程式設計的支援。類將結構化的資料及對其進行操作的過程或函式封裝在一起。允許使用者根據現實世界的物件建模,而不必再將其抽象成關係資料。

DM7的類型別分為普通類型別和JAVA CLASS型別。DM文件中的示例除了特別宣告使用的是JAVA CLASS型別,要不然使用的都是普通類型別。

普通CLASS型別
DM7的類的定義分為類頭和類體兩部分,類頭完成類的宣告;類體完成類的實現。類中可以包括以下內容:
1. 型別定義
在類中可以定義遊標、異常、記錄型別、陣列型別、以及記憶體索引表等資料型別,在類的宣告及實現中可以使用這些資料型別;類的宣告中不能宣告遊標和異常,但是實現中可以定義和使用。
2. 屬性
類中的成員變數,資料型別可以是標準的資料型別,可以是在類中自定義的特殊資料型別。
3. 成員方法
類中的函式或過程,在類頭中進行宣告;其實現在類體中完成;
成員方法及後文的建構函式包含一個隱含引數,即自身物件,在方法實現中可以透過this或self來訪問自身物件,self等價於this。如果不存在重名問題,也可以直接使用物件的屬性和方法。this和self只能在包或物件指令碼中呼叫。

4. 建構函式
建構函式是類內定義及實現的一種特殊的函式,這類函式用於例項化類的物件,建構函式滿足以下條件:
1) 函式名和類名相同;
2) 函式返回值型別為自身類。
建構函式存在以下的約束:
1) 系統為每個類提供兩個預設的建構函式,分別為0參的建構函式和全參的建構函式;
2) 0參建構函式的引數個數為0,例項的物件內所有的屬性初始化值為NULL;
3) 全參建構函式的引數個數及型別和類內屬性的個數及屬性相同,按照屬性的順序依次讀取引數的值並給屬性賦值;
4) 使用者可以自定義建構函式,一個類可以有多個建構函式,但每個建構函式的引數個數必須不同;
5) 如果使用者自定義了0個引數、或引數個數同屬性個數相同的建構函式,則會覆蓋相應的預設建構函式。

下面從類的宣告、類的實現、類的刪除、類體的刪除和類的使用幾部分來詳細介紹類型別的實現過程。
類的宣告在類頭中完成。類頭定義透過CREATE CLASS語句來完成,其語法為:
語法格式
CREATE [OR REPLACE] CLASS [< 模式名>.]< 類名> [WITH ENCRYPTION] [UNDER [< 模式名>.]< 父類名>] [[NOT] FINAL] [[NOT]
INSTANTIABLE] [AUTHID DEFINER | AUTHID CURRENT_USER] AS|IS < 類內宣告列表> END [類名]
< 類內宣告列表> ::= < 類內宣告>;{< 類內宣告>;}
< 類內宣告> ::= < 變數定義>|< 過程定義>|< 函式定義>|< 型別聲名>
< 變數定義> ::= < 變數名列表> < 資料型別> [預設值定義]
< 過程定義> ::= [< 方法繼承屬性>][STATIC|MEMBER] PROCEDURE < 過程名> < 引數列表>
< 函式定義> ::= [< 方法繼承屬性>] [MAP] [STATIC|MEMBER] FUNCTION < 函式名>< 引數列表> RETURN < 返回值資料型別>[DETERMINISTIC]
[PIPELINED]
< 方法繼承屬性> ::= < 過載屬性> | | < 過載屬性>
< 過載屬性> ::= [NOT] OVERRDING
::= FINAL | NOT FINAL | INSTANTIABLE | NOT INSTANTIABLE
< 型別聲名> ::= TYPE < 型別名稱> IS < 資料型別>

使用說明
1.類中元素可以以任意順序出現,其中的物件必須在引用之前被宣告;
2.過程和函式的宣告都是前向宣告,類宣告中不包括任何實現程式碼;
3.支援物件靜態方法宣告與呼叫。可以在PROCEDURE/FUNCTION關鍵字前新增static保留字,以此指明方法為靜態方法。靜態方法只能以物件名為字首呼叫,而不能在物件例項中呼叫;
4.支援物件成員方法宣告與呼叫。可以在PROCEDURE/FUNCTION關鍵字前新增MEMBER以指明方法為成員方法。MEMBER與STATIC不能同時使用,非STATIC型別的非建構函式方法預設為成員方法。MAP表示將物件型別的例項對映為標量數值,只能用於成員型別的FUNCTION;
5.關於類繼承,有以下使用限制:
1) 類定義預設為FINAL,表示該物件型別不能被繼承,定義父類時必須指定NOT FINAL選項;
2) 定義子類時必須指定UNDER選項;
3) NOT INSTANTIABLE物件不能為FINAL;
4) NOT INSTANTIABLE物件不能例項化,但是可以用其子類賦值;
5) 物件例項化時,必須對父類和子類的成員變數都賦值,且從父類到子類逐個賦值;
6) 不支援物件的迴圈繼承;
7) 不支援物件的多繼承,即一個類有多個父類;
6) 不支援物件的迴圈繼承;
7) 不支援物件的多繼承,即一個類有多個父類;
8) 不支援父類和子類包含同名變數;
9) 父類和子類可以同名同參,此時子類必須指定OVERRIDING;
10) 方法預設為NOT OVERRIDING,OVERRIDING不能與static一起使用;
11) 父類和子類支援同名不同參(引數個數不同、引數個數相同但型別不同)的方法;
12) 同名且引數個數相同但型別不同時,根據引數型別選擇使用的方法;
13) 方法預設為INSTANTIABLE,如果宣告為NOT INSTANTIABLE,則不能與FINAL、STATIC一起使用;
14) 如果父類有多個NOT INSTANTIABLE方法,子類可以只部分重寫,但此時子類必須定義為NOT FINAL NOT INSTANTIABLE;
15) NOT INSTANTIABLE方法不能具有主體;
16) 方法預設為NOT FINAL,如果宣告為FINAL,則不能被子類重寫;
17) 子類可以賦值給父類;
18) 如果父類對應的例項是子類或者子類的孩子,則該父類可以賦值給子類;
19) 可以用INSTANTIABLE子類對NOT INSTANTIABLE父類進行賦值;
20) 子類例項賦值給父類後,呼叫時使用的是父類方法而不是子類方法;
21) 支援使用as語句轉換為父類。

所需許可權
1、使用該語句的使用者必須是DBA或具有CREATE CLASS資料庫許可權的使用者;
2、可以用關鍵字AUTHID DEFINER |AUTHID CURRENT_USER指定類的呼叫者許可權,若為DEFINER,則採用類定義者許可權,若為CURRENT_USER則為當前使用者許可權,預設為類定義者許可權。

類的實現透過類體完成。類體的定義透過CREATE CLASS BODY語句來完成,其語法為:
語法格式
CREATE [OR REPLACE] CLASS BODY [< 模式名>.]< 類名> [WITH ENCRYPTION] AS|IS < 類體部分> END [類名]
< 類體部分> ::= < 過程/函式列表> [< 初始化程式碼>]
< 過程/函式列表> ::= < 過程實現|函式實現>{,< 過程實現|函式實現> }
< 過程實現> ::= [< 方法繼承屬性>][STATIC|MEMBER]PROCEDURE < 過程名> < 引數列表> AS|IS BEGIN < 實現體> END [過程名]
< 函式實現> ::= [< 方法繼承屬性>][MAP] [STATIC|MEMBER]FUNCTION < 函式名>< 引數列表> RETURN < 返回值資料型別>[DETERMINISTIC] [PIPELINED] AS|IS BEGIN < 實現體> END [函式名]
< 方法繼承屬性> ::= < 過載屬性> | | < 過載屬性>
< 過載屬性> ::= [NOT] OVERRDING
::= FINAL | NOT FINAL | INSTANTIABLE | NOT INSTANTIABLE
< 初始化程式碼> ::= [[< 說明部分>]BEGIN< 執行部分>[< 異常處理部分>]]
< 說明部分> ::=[DECLARE]< 說明定義>{< 說明定義>}
< 說明定義>::=< 變數說明>|< 異常變數說明>|< 遊標定義>|< 子過程定義>|< 子函式定義>
< 變數說明>::=< 變數名>{,< 變數名>}< 變數型別>[DEFAULT|ASSIGN|:=< 表示式>];
< 變數型別>::=|< [模式名.]表名.列名%TYPE>|< [模式名.]表名%ROWTYPE>|< 記錄型別>
< 記錄型別>::= RECORD(< 變數名> {,< 變數名> })
< 異常變數說明>::=< 異常變數名>EXCEPTION[FOR< 錯誤號>]
< 異常處理語句>::= WHEN < 異常名> THEN < SQL過程語句序列>

使用說明
1. 類宣告中定義的物件對於類體而言都是可見的,不需要宣告就可以直接引用。這些物件包括變數、遊標、異常定義和型別定義;
2. 類體中的過程、函式定義必須和類宣告中的宣告完全相同。包括過程的名字、引數定義列表的引數名和資料型別定義;
3. 類中可以有重名的成員方法,要求其引數定義列表各不相同。系統會根據使用者的呼叫情況進行過載(OVERLOAD);
4. 宣告類與實現類時,對於確定性函式的指定邏輯與包內函式相同。目前不支援類的確定性函式在函式索引中使用。

所需許可權
使用該語句的使用者必須是DBA或該類物件的擁有者且具有CREATE CLASS資料庫許可權的使用者。
完整的類頭、類體的建立如下所示:
----類頭建立

SQL> create or replace class mycls
2   as
3   type rec_type is record (c1 int, c2 int); --型別宣告
4   id int; --成員變數
5   r rec_type; --成員變數
6   function f1(a int, b int) return rec_type; --成員函式
7   function mycls(id int , r_c1 int, r_c2 int) return mycls;
8   --使用者自定義建構函式
9   end;
10  /
executed successfully
used time: 14.032(ms). Execute id is 106.

----類體建立

SQL> create or replace class body mycls
2   as
3    function f1(a int, b int) return rec_type
4    as
5    begin
6     r.c1 = a;
7     r.c2 = b;
8     return r;
9    end;
10   function mycls(id int, r_c1 int, r_c2 int) return mycls
11   as
12   begin
13    this.id = id; --可以使用this.來訪問自身的成員
14    r.c1 = r_c1; --this也可以省略
15    r.c2 = r_c2;
16    return this; --使用return this 返回本物件
17   end;
18  end;
19  /
executed successfully
used time: 61.783(ms). Execute id is 107.

重編譯類
重新對類進行編譯,如果重新編譯失敗,則將類置為禁止狀態。
重編功能主要用於檢驗類的正確性。
語法格式
ALTER CLASS [< 模式名>.]< 類名> COMPILE [DEBUG];

引數
1.< 模式名> 指明被重編譯的類所屬的模式;
2.< 類名> 指明被重編譯的類的名字;
3.[DEBUG] 可忽略。

所需許可權
執行該操作的使用者必須是類的建立者,或者具有DBA許可權。
舉例說明
例如重新編譯類

SQL> ALTER CLASS mycls COMPILE;
executed successfully
used time: 8.867(ms). Execute id is 108.

刪除類
類的刪除分為兩種方式:一是類頭的刪除,刪除類頭則會順帶將類體一起刪除;另外一種是類體的刪除,這種方式只能刪除類體,類頭依然
存在。

刪除類頭
類的刪除透過DROP CLASS完成,即類頭的刪除。刪除類頭的同時會一併刪除類體。
語法格式
DROP CLASS [< 模式名>.]< 類名>[RESTRICT | CASCADE]; 使用說明
1.如果被刪除的類不屬於當前模式,必須在語句中指明模式名;
2.如果一個類的宣告被刪除,那麼對應的類體被自動刪除。

所需許可權
執行該操作的使用者必須是該類的擁有者,或者具有DBA許可權。

刪除類體
從資料庫中刪除一個類的實現主體物件。
語法格式
DROP CLASS BODY [< 模式名>.]< 類名>[RESTRICT | CASCADE]; 使用說明
如果被刪除的類不屬於當前模式,必須在語句中指明模式名。
許可權
執行該操作的使用者必須是該類的擁有者,或者具有DBA許可權。

類的使用
類型別同普通的資料型別一樣,可以作為表中列的資料型別,DMSQL程式語句塊中變數的資料型別或過程及函式引數的資料型別。

具體使用規則
1.作為表中列型別或其他類成員變數屬性的類不能被修改,刪除時需要指定CASCADE級聯刪除類中定義的資料型別,其名稱只在類的宣告及實現中有效。如果類內的函式的引數或返回值是類內的資料型別,或是進行類內成員變數的複製,需要在DMSQL程式中定義一個結構與之相同的型別。

根據類使用方式的不同,物件可分為變數物件及列物件。變數物件指的是在DMSQL程式語句塊中宣告的類型別的變數;列物件指的是在表中類型別的列。變數物件可以修改其屬性的值而列物件不能。

2.變數物件的例項化
類的例項化透過NEW 表示式呼叫建構函式完成。
3.變數物件的引用
透過‘=’進行的類型別變數之間的賦值所進行的是物件的引用,並沒有複製一個新的物件。

4.變數物件屬性訪問
可以透過如下方式進行屬性的訪問。
< 物件名>.< 屬性名>
5.變數物件成員方法呼叫
成員方法的呼叫透過以下方式呼叫:
< 物件名>.< 成員方法名>(< 引數>{,< 引數>})
如果函式內修改了物件內屬性的值,則該修改生效。
6.列物件的插入
列物件的建立是透過INSERT語句向表中插入資料完成,插入語句中的值是變數物件,插入後儲存在表中的資料即為列物件。
7.列物件的複製
儲存在表中的物件不允許對物件中成員變數的修改,透過into查詢或’=’進行的列到變數的賦值所進行的是物件的賦值,生成了一個與列物件資料一樣的副本,在該副本上進行的修改不會影響表中列物件的值。
8.列物件的屬性訪問
透過如下方式進行屬性的訪問:
< 列名>.< 屬性名>
9.列物件的方法呼叫
< 列名>.< 成員方法名>(< 引數>{,< 引數>})
列物件方法呼叫過程中對型別內屬性的修改,都是在列物件的副本上進行的,不會影響列物件的值。

應用例項
1. 變數物件的應用例項

SQL> declare
2     type ex_rec_t is record (a int, b int); --使用一個同結構的型別代替類定義的型別
3     rec ex_rec_t;
4     o1 mycls;
5     o2 mycls;
6   begin
7     o1 = new mycls(1,2,3);
8     o2 = o1; --物件引用
9     rec = o2.r; --變數物件的成員變數訪問
10    print rec.a; print rec.b;
11    rec = o1.f1(4,5); --成員函式呼叫
12    print rec.a; print rec.b;
13    print o1.id; --成員變數訪問
14  end;
15  /
2
3
4
5
1
DMSQL executed successfully
used time: 3.129(ms). Execute id is 109.

2. 列物件的應用例項
表的建立。

SQL> create table tt1(c1 int, c2 mycls);
executed successfully
used time: 28.302(ms). Execute id is 112.

列物件的建立--插入資料。

SQL> insert into tt1 values(1, mycls(1,2,3));
affect rows 1
used time: 22.639(ms). Execute id is 113.
SQL> commit;
executed successfully
used time: 17.285(ms). Execute id is 114.

列物件的複製及訪問。

SQL> declare
2     o mycls;
3     id int;
4   begin
5     select top 1 c2 into o from tt1; --列物件的複製
6     select top 1 c2.id into id from tt1; --列物件成員的訪問
7   end;
8   /
DMSQL executed successfully
used time: 33.518(ms). Execute id is 115.

3. 類繼承的應用例項

SQL> CREATE OR REPLACE CLASS cls01 NOT FINAL IS
2     name VARCHAR2(10);
3     MEMBER FUNCTION get_info RETURN VARCHAR2;
4   END;
5   /
executed successfully
used time: 22.220(ms). Execute id is 116.
SQL> CREATE OR REPLACE CLASS cls02 UNDER cls01 IS
2     ID INT;
3     OVERRIDING MEMBER FUNCTION get_info RETURN VARCHAR2;
4   END;
5   /
executed successfully
used time: 14.072(ms). Execute id is 117.

JAVA CLASS型別
JAVA類的定義類似JAVA語言語法,類中可定義。
JAVA類中可以包括以下內容:
1. 型別定義
在類中可以定義遊標、異常,可以宣告記錄型別、陣列型別、結構體型別以及記憶體索引表等資料型別變數。
2. 屬性
類中的成員變數,資料型別可以是標準的資料型別,可以是在類外自定義的特殊資料型別。
3. 成員方法
JAVA類中的成員方法及後文的建構函式包含一個隱含引數,即自身物件,在方法實現中可以透過this或self來訪問自身物件,self等價於this。如果不存在重名問題,也可以直接使用物件的屬性和方法。
4. 建構函式
建構函式是類內定義及實現的一種特殊的函式,這類函式用於例項化類的物件,建構函式滿足以下條件:
1) 函式名和類名相同;
2) 函式沒有返回值型別。
建構函式存在以下的約束:
1) 系統為每個類提供兩個預設的建構函式,分別為0參的建構函式和全參的建構函式;
2) 0參建構函式的引數個數為0,例項的物件內所有的屬性初始化值為NULL;
3) 全參建構函式的引數個數及型別和類內屬性的個數及屬性相同,按照屬性的順序依次讀取引數的值並給屬性賦值;
4) 使用者可以自定義建構函式,一個類可以有多個建構函式,但每個建構函式的引數個數必須不同;
5) 如果使用者自定義了0個引數、或引數個數同屬性個數相同的建構函式,則會覆蓋相應的預設建構函式。

定義JAVA類
定義透過CREATE JAVA CLASS語句來完成,其語法為:
語法格式
CREATE [OR REPLACE] JAVA [PUBLIC] [ABSTRACT] [FINAL] CLASS < 類名> [EXTENDS [< 模式名>.]< 父類名>] {< 類內定義部分> }
< 類內定義部分> ::= < 類內定義列表>
< 類內定義列表> ::= < 類內定義>;{< 類內定義>;}
< 類內定義> ::= [PUBLIC|PRIVATE] < 變數定義>|< 方法定義>
< 變數定義> ::= < 變數屬性> < 資料型別>< 變數名列表> [預設值定義]
< 變數屬性> ::= [STATIC]
< 方法定義> ::= [PUBLIC|PRIVATE] [< 方法繼承屬性>] [STATIC] < 返回型別> < 函式名>< 引數列表> { < 實現體> }
< 方法繼承屬性> ::= < 過載屬性> | |
::= ABSTRACT
::= FINAL
< 過載屬性> ::= OVERRIDE

使用說明
1.類中元素可以以任意順序出現,其中的物件必須在引用之前被宣告。
2.支援物件靜態方法宣告與呼叫。可以在方法前新增static保留字,以此指明方法為靜態方法。靜態方法只能以物件名為字首呼叫,而不能在物件例項中呼叫。
3.支援物件成員方法宣告與呼叫。非STATIC型別的非建構函式方法預設為成員方法。成員方法呼叫時,需要先例項化,例項化引數值預設為null。
4. 變數定義還包括遊標、異常定義。
5.方法屬性是PUBLIC,則訪問類時可以訪問,如果是PRIVATE屬性,則訪問類時不可以訪問該方法。
6.關於JAVA 類繼承,有以下使用限制:
1) JAVA CLASS定義預設可繼承,FINAL表示該類不能被繼承;
2) 定義子類時必須指定EXTENDS選項;
3) ABSTRACT物件不能為FINAL;
4) ABSTRACT物件不能例項化,但是可以用其子類賦值;
5) 子類物件例項化時,必須對父類和子類的成員變數都賦值,且從父類到子類逐個賦值;
6) 不支援物件的迴圈繼承;
7) 不支援物件的多繼承,即一個類只能有一個父類;
8) 不支援父類和子類包含同名變數;
9) 父類和子類可以同名同參,此時子類必須指定OVERRIDE;
10) 方法預設為NOT OVERRIDING,OVERRIDING不能與static一起使用;
11) 父類和子類支援同名不同參(引數個數不同、引數個數相同但型別不同)的方法;
12) 同名且引數個數相同但型別不同時,根據引數型別選擇使用的方法;
13) 方法如果宣告為ABSTRACT,則不能與FINAL、STATIC一起使用;
14) 如果父類有多個ABSTRACT方法,子類可以只部分重寫,但此時子類必須定義為ABSTRACT;
15) ABSTRACT方法不能具有主體;
16) 方法預設為可繼承,如果宣告為FINAL,則不能被子類重寫;
17) 子類可以賦值給父類;
18) 如果父類對應的例項是子類或者子類的孩子,則該父類可以賦值給子類;
19) 可以用ABSTRACT子類對非ABSTRACT父類進行賦值;
20) 子類例項賦值給父類後,呼叫時使用的是父類方法而不是子類方法;
21) 支援使用super無參方法轉換為父類引用;
22) 支援使用this()呼叫該類建構函式,super()呼叫父類建構函式;
23) 子類必須有新增成員或方法,不能完全為空。

重編譯JAVA類
重新對JAVA類進行編譯,如果重新編譯失敗,則將JAVA類置為禁止狀態。
重編功能主要用於檢驗JAVA類的正確性。
語法格式
ALTER JAVA CLASS [< 模式名>.] COMPILE [DEBUG];
引數
1.< 模式名> 指明被重編譯的JAVA類所屬的模式;
2. 指明被重編譯的JAVA類的名字;
3.[DEBUG] 可忽略。

所需許可權
執行該操作的使用者必須是JAVA類的建立者,或者具有DBA許可權。
12.2.3 刪除JAVA類
JAVA類的刪除透過DROP CLASS完成。
語法格式
DROP CLASS < 類名>[RESTRICT | CASCADE];

類的使用
下面列舉一個簡單的應用例項。在列物件上如何使用JAVA CLASS。
1.建立JAVA CLASS。

SQL> create or replace java class jcls
2   {
3     int a;
4     public static int testAdd2(int a, int b)
5     { //此處建立的是靜態STATIC方法
6       return a + b;
7     }
8     public int testAdd3(int a, int b, int c)
9     { //此處建立的是成員方法
10     return a + b +c;
11    }
12  };
13  /
executed successfully
used time: 16.964(ms). Execute id is 123.

2. 在列物件中使用JAVA CLASS。

SQL> create table tt2(c1 int, c2 jcls);
executed successfully
used time: 9.261(ms). Execute id is 124.
SQL> insert into tt2 values(jcls.testadd2(1,2),jcls(1)); //靜態方法呼叫
2   /
affect rows 1
used time: 1.255(ms). Execute id is 125.
SQL> insert into tt2 values(jcls().testadd3(1,2,3),jcls(2)); //成員方法呼叫之前必須例項化
2   /
affect rows 1
used time: 1.023(ms). Execute id is 126.

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26015009/viewspace-2681032/,如需轉載,請註明出處,否則將追究法律責任。

相關文章