3.5 オブジェクトリレーショナルデータベースへの拡 張
3.5.2 サブタイプと継承
(6) 抽象データ型の値の操作
従業員に対して,勤続年数を算出するという操作を考えます。
HiRDB では,CREATE TYPEのルーチン宣言で,抽象データ型の値に対する操作を定義できます。例え ば,「勤続年数」算出や「報酬率」算出の操作を次に示す定義系 SQL で定義できます。
CREATE TYPE t_従業員 ( 氏名 CHAR(16), 性別 CHAR(1), 入社年月日 DATE, 役職 CHAR(10), 顔写真 BLOB(64K), 基本給 INTEGER, …
FUNCTION 勤続年数 ( p t_従業員 ) RETURNS INTEGER
BEGIN
DECLARE working_years INTERVAL YEAR TO DAY;
SET working_years = CURRENT_DATE - p..入社年月日;
RETURN YEAR(working_years);
END, … )
このように,抽象データ型で定義したルーチンをその抽象データ型の値に対して使用できます。例えば,勤 続年数が 10 年以上の社員の社員番号と氏名を検索する SQL は,次のように記述できます。
SELECT 社員番号, 従業員..氏名, 勤続年数(従業員) FROM 社員表
WHERE 勤続年数(従業員) >= 10
図 3‒40 実世界の情報と抽象データ型による概念モデル(営業部員の場合)
HiRDB では,あるデータ型を基にその型を特化した抽象データ型をサブタイプとして定義できます。
例えば,定義系 SQL 文 CREATE TYPEのサブタイプ句を使用して,t_従業員を基に,t_営業部員を次に示 すように定義できます。
CREATE TYPE t_営業部員 UNDER t_従業員(
担当顧客 VARCHAR(3000), FUNCTION 顧客総数 ( … ) RETURNS INTEGER
… )
なお,t_従業員のような,サブタイプに対する上位の抽象データ型をスーパタイプといいます。
(2) 代替可能性(substitutability)
「営業部員」は「従業員」でもあります。HiRDB では,サブタイプで特化した(下位の)抽象データ型の 値をその上位の抽象データ型の値としても扱えます。例えば,社員表では次に示す SQL で,t_営業部員の 値をt_従業員の値として列の値にできます。
3 データベースの論理構造
105
注意事項
t_営業部員の値も t_従業員の値と同様に扱えるようにするために,この SQL を実行する前に,ALTER ROUTINE を実行し,SQL オブジェクトを再作成しておく必要があります。
INSERT INTO 社員表 VALUES ( 51, t_営業部員(:name AS CHAR(16),…) )
このように,下位の抽象データ型の値が上位の抽象データ型の値としてみなされることを代替可能性
(substitutability)といいます。
(3) 継承(inheritance)
「営業部員」は「従業員」でもあるので,「従業員」と同様に「氏名」や「性別」の属性を持ち,「勤続年数」
算出の操作が適用できると考えられます。
図 3-40 のように,HiRDB ではサブタイプで特化した(下位の)抽象データ型にその上位の抽象データ型 に定義された属性とルーチンが引き継がれます。
このように,下位の抽象データ型が,上位の抽象データ型の属性及びルーチンを引き継ぐことを継承
(inheritance)といいます。
例えば,継承によってt_営業部員の値に対して属性「氏名」と操作「勤続年数」が利用できるようになる ため,t_営業部員の値を列値に挿入した社員表について,次に示す SQL のように,先に示した SQL を変 更することなく実行できます。
注意事項
この SQL を実行する前に,ALTER ROUTINE を実行し,SQL オブジェクトを再作成しておく必要が あります。
SELECT 社員番号, 従業員..氏名, 勤続年数(従業員) FROM 社員表
WHERE 勤続年数(従業員) >= 10
サブタイプと継承で,次に示す効果が期待できます。
• 「営業部員」が「従業員」であるという代替可能性の概念を簡潔に表現できます。
• 属性及びルーチンの定義を共有し,既存の定義を基に新しい定義を追加できます。そのため,データ ベース及びアプリケーション開発のオーバヘッドを削減でき,拡張性のあるシステムを構築できます。
(4) 多重定義(override)
「従業員」に対して「報酬」を査定する操作を考えます。報酬の査定は,例えば,「基本給」,「勤続年数」,
「勤続年数に基づく報酬率」によって設定された情報を基に,作業状況を評価して査定することが考えられ ます。
一方で,継承によって「従業員」に定義される操作「報酬」は自動的に「営業部員」に引き継がれます。し かし,特に営業部員については,一般的な従業員の査定方法とは異なり,営業活動で注文を受けた「顧客総 数」などを基に,営業部員特有の査定をすることが考えられます。
実世界での従業員,営業部員についての操作を次の図に示します。
図 3‒41 実世界での従業員,営業部員についての操作
例えば,「従業員報酬」や「営業部員報酬」のような,それぞれの抽象データ型ごとに異なる名称のルーチ ンを定義するとします。その場合,代替可能性で「従業員」の値と「営業部員」の値を統一的に扱えるのに もかかわらず,それぞれの値の型によって呼び出すルーチンの名称を変更しなければならなくなります。そ のため,アプリケーションでは次に示す操作系 SQL を実行できなくなります。
× SELECT 社員番号, 従業員..氏名, 従業員報酬(従業員) FROM 社員表
…「営業部員」に対して,営業部員特有の報酬査定を実行できません。
× SELECT 社員番号, 従業員..氏名, 営業部員報酬(従業員) FROM 社員表
…「営業部員」でない「従業員」に対しても,営業部員特有の報酬査定を実行してしまいます。
HiRDB では,上位の抽象データ型で定義されたルーチンと同じ名前のルーチンを下位の抽象データ型を定 義するときに上書きして定義できます。このように上書きして定義することを多重定義(override)といい ます。
多重定義を次の図に示します。
3 データベースの論理構造
107
図 3‒42 多重定義
また,多重定義されたルーチンの実行では,その引数となる値の型に応じて,HiRDB が自動的に適切な定 義に従って実行します。多重定義によって,呼び出すルーチンの名称を値の型によって変更する必要がなく なります。そのため,次に示す操作系 SQL を実行できます。
注意事項
この SQL を実行する前に,ALTER ROUTINE を実行し,SQL オブジェクトを再作成しておく必要が あります。
SELECT 社員番号, 従業員..氏名, 報酬(従業員) FROM 社員表
…多重定義したルーチン「報酬」によって,実行時にそれぞれの引数の値に応じたルーチンが実行されま す。
この SQL の実行では,t_従業員型の値に対しては,t_従業員型に定義されたルーチン「報酬」が実行され,
t_営業部員型の値に対しては,t_営業部員型に定義されたルーチン「報酬」が実行されます。
なお,上記の SQL のように,アプリケーションではルーチンが多重定義されているかどうかを意識しない でルーチンを呼び出せます。また,多重定義によってルーチンを追加した場合でも,アプリケーションを変 更しないで SQL を実行できるようになります。