3.5 オブジェクトリレーショナルデータベースへの拡 張
3.5.1 抽象データ型
3.5 オブジェクトリレーショナルデータベースへの拡
実世界の情報と抽象データ型による概念モデルを次の図に示します。
図 3‒35 実世界の情報と抽象データ型による概念モデル
抽象データ型は,次に示す定義系 SQL の CREATE TYPE によってデータベースに定義できます。
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, … )
このように抽象データ型を定義すると,更にユーザがその抽象データ型の属性及び操作を指定して,新たな データ型を定義できます。なお,操作はルーチンに定義できます。
(2) データ型としての抽象データ型
抽象データ型は,数値型や文字型などの HiRDB の既定義型と同様に扱えます。例えば,次に示す定義系 SQL によって,抽象データ型 t_従業員 を列のデータ型として,表 社員表 を定義できます。
CREATE TABLE 社員表 ( 社員番号 INTEGER,
従業員 t_従業員 ALLOCATE (顔写真 IN (lobarea) ) )
抽象データ型の属性の中で,BLOB 型の属性がある場合には,そのデータを格納するユーザ LOB 用 RD エ リアをCREATE TABLEのALLOCATEで指定します。上記の例では,t_従業員の属性である顔写真が BLOB 型であるため,ALLOCATE を使用してユーザ LOB 用 RD エリア lobarea に格納しています。抽 象データ型を定義した社員表を次の図に示します。
図 3‒36 抽象データ型を定義した社員表
(3) カプセル化
抽象データ型を使用した場合,アプリケーションでは,その抽象データ型に宣言されたルーチンを使用する ことで,個々の属性の詳細な構成やルーチンの実装を知らなくても,抽象データ型の値を扱えるようになり ます。例えば,次に示す操作系 SQL で,t_従業員型の値を操作できます。
SELECT 社員番号, 従業員..氏名, 勤続年数(従業員) FROM 社員表
このように,抽象データ型によって,値の内部情報を意識させないようにして,外部的なインタフェースだ けで値を扱えるようにすることをカプセル化といいます。
カプセル化の概要を次の図に示します。
図 3‒37 カプセル化の概要
(4) 抽象データ型の値
(a) 値の生成
抽象データ型と同じ名前で識別される引数のない関数を実行して,その抽象データ型の値を生成できます。
例えば,t_従業員型 の場合には,関数 t_従業員() で,t_従業員型 の値を生成できます。このように,抽象 データ型の値を生成する関数をコンストラクタ関数といいます。
3 データベースの論理構造
101
BEGIN … SQL手続き文の始まり DECLARE p t_従業員; … t_従業員型の変数宣言
SET p = t_従業員(); … t_従業員型の値を生成し,変数に代入
SET p..氏名 = 'イトウエイイチ' … コンポネント指定による属性値の設定 RETURN p; … 関数の戻り値の返却(t_従業員型の値を返す)
END … SQL手続き文の終わり
CREATE TYPEで抽象データ型をデータベースに定義すると,t_従業員()のような,データ型名が同じで引 数のない関数が自動的に定義されます。このような関数を特にデフォルトコンストラクタ関数といいます。
(b) ユーザ定義のコンストラクタ関数
コンストラクタ関数をユーザが定義することもできます。CREATE TYPEのルーチン宣言で,定義する抽 象データ型と同じ名前でその抽象データ型を戻り値の型とする関数を定義すると,コンストラクタ関数を定 義できます。
CREATE TYPE t_従業員 ( 氏名 CHAR(16), 性別 CHAR(1), 入社年月日 DATE, 役職 CHAR(10), 顔写真 BLOB(64K), 基本給 INTEGER, FUNCTION t_従業員(
p_氏名 CHAR(16), p_性別 CHAR(1), p_入社年月日 DATE, p_役職 CHAR(10), p_顔写真 BLOB(64K), p_基本給 INTEGER) RETURNS t_従業員 BEGIN
DECLARE d_従業員 t_従業員;
SET d_従業員 = t_従業員();
SET d_従業員..氏名 = p_氏名;
SET d_従業員..性別 = p_性別;
SET d_従業員..入社年月日 = p_入社年月日;
SET d_従業員..役職 = p_役職;
SET d_従業員..顔写真 = p_顔写真;
SET d_従業員..基本給 = p_基本給;
RETURN d_従業員;
END, … )
例えば,ユーザ定義のコンストラクタ関数 t_従業員() を使用して,次に示す操作系 SQL で値を生成し,
データベースに格納できます。
INSERT INTO 社員表 VALUES ( 650056,
t_従業員(:name AS CHAR(16), :sex AS CHAR(1), :yrs AS DATE,
:post AS CHAR(10), :picture AS BLOB(64K) ,:salary AS INTEGER) )
コンストラクタ関数 t_従業員() によって値を生成し,列値として挿入した表 社員表を次の図に示します。
図 3‒38 コンストラクタ関数によって値を生成した表 社員表
(5) 抽象データ型のナル値
HiRDB の既定義型と同様に,抽象データ型にもナル値を適用できます。例えば,前述の社員表について次 に示す操作系 SQL を実行した場合,列 従業員の値はナル値になります。
INSERT INTO 社員表(社員番号) VALUES ( 650056 )
一方,次に示す操作系 SQL を実行すると,t_従業員型の全属性の値がナル値になります。なお,すべての 属性の値がナル値であるような抽象データ型の値は,ナル値ではない値とみなされます。
INSERT INTO 社員表 (900123, t_従業員())
抽象データ型を定義した社員表でのナル値の扱いを次の図に示します。
図 3‒39 抽象データ型を定義した社員表でのナル値の扱い
例えば,次に示す操作系 SQL を実行すると,列 従業員の値がナル値ではない従業員の社員番号が検索され るため,t_従業員型のすべての属性がナル値である従業員の社員番号は検索されます。
SELECT 社員番号 FROM 社員表 WHERE 従業員 IS NOT NULL 検索結果
900123
3 データベースの論理構造
103
(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