6.13 オブジェクト・ビューにおける複雑なリレーションシップの定義
オブジェクト・ビューには、MAKE_REF演算子を使用して、循環参照を定義できます。view_Aはview_Bを参照でき、view_Bはview_Aを参照できます。これにより、オブジェクト・ビューではグラフのような複雑な構造をリレーショナル・データから合成できるようになります。
たとえば、部門および従業員の例の場合、部門オブジェクトに従業員のリストが含まれています。領域を節約するために、部門オブジェクト内のすべての従業員を具体化せずに、従業員オブジェクトの参照を、部門オブジェクト内部に入れてみます。従業員オブジェクトへの参照を構成(確保)し、後でドット表記法を使用してこの参照に従い、従業員情報を抽出できます。
従業員オブジェクトはすでに従業員の所属部門への参照を持っているため、このモデルでのオブジェクト・ビューには、部門ビューと従業員ビューの間の循環参照が含まれます。
オブジェクト・ビュー間の循環参照は、次の2通りの方法で作成できます。
注意:
循環参照の作成方法ではいずれも、「循環参照を示す表および型」に示されている設定を実行する必要があります。
-
2つ目のビューを作成した後、最初のビューを作成する
-
ビューBへの参照を持たないビューAを作成します。
-
ビューAへの参照を含むビューBを作成します。
-
ビューAをビューBの参照を含む新しい定義で置換します。
「方法1: 2つ目のビューを作成した後、最初のビューを再作成する」の例を参照してください
-
-
FORCEキーワードを使用して最初のビューを作成する-
FORCEキーワードを使用して、ビューBへの参照を持つビューAを作成します。 -
ビューAの参照を持つビューBを作成します。ビューAを使用すると、妥当性チェックが行われ、再コンパイルされます。
「方法2: FORCEキーワードを使用して最初のビューを作成する」の例を参照してください
-
方法2の方が、手順が簡単ですが、ビューの作成時に、FORCEキーワードによりエラーが隠される可能性があります。ビュー作成中にエラーが発生したかどうかを確認するには、USER_ERRORSカタログ・ビューを問い合せる必要があります。ビュー作成文の中にエラーがないことが保証されている場合にのみ、この方法を使用してください。
また、使用時にエラーによってビューが再コンパイルできない場合は、ALTER VIEW COMPILEコマンドを使用し、ビューを手動で再コンパイルする必要があります。
循環ビュー参照の作成では、いずれの方法を使用する場合も、あらかじめ次に説明する設定を実行してください。
6.13.1 循環参照を示す表および型
まず、リレーショナル表および対応付けられたオブジェクト型を設定する必要があります。表にオブジェクトが入っていても、この表はオブジェクト表ではありません。データ・オブジェクトにアクセスするために、後でオブジェクト・ビューを作成します。
emp表には、従業員情報が入っています。
例6-10 循環参照を示すemp表の作成
CREATE TABLE emp ( empno NUMBER PRIMARY KEY, empname VARCHAR2(20), salary NUMBER, deptno NUMBER ); -- first create a dummy, that is, incomplete, department type, so emp_t type -- created later will succeed CREATE TYPE dept_t; / -- Create the employee type with a reference to the department,dept_t: CREATE TYPE emp_t AS OBJECT ( eno NUMBER, ename VARCHAR2(20), salary NUMBER, deptref REF dept_t ); / -- Represent the list of references to employees as a nested table: CREATE TYPE employee_list_ref_t AS TABLE OF REF emp_t; / -- Create the department table as a relational table CREATE TABLE dept ( deptno NUMBER PRIMARY KEY, deptname VARCHAR2(20), deptstreet VARCHAR2(20), deptcity VARCHAR2(10), deptstate CHAR(2), deptzip VARCHAR2(10) ); -- Create object types that map to columns from the relational tables: CREATE TYPE address_t AS OBJECT ( street VARCHAR2(20), city VARCHAR2(10), state CHAR(2), zip VARCHAR2(10)); / -- Fill in the definition fordept_t, the incomplete type you previously created: CREATE OR REPLACE TYPE dept_t AS OBJECT ( dno NUMBER, dname VARCHAR2(20), deptaddr address_t, empreflist employee_list_ref_t); /
例6-10に示すように、emp表を作成してから、ダミーの部門型dept_tを作成する必要があります。これにより、emp_t型が作成されると正常に機能できるようになります。その後、dept_tへの参照を持つemp_tを作成します。ネストした表employee_list_ref_tとして従業員への参照のリストを作成し、部門表deptを作成します。次に、リレーショナル表にマップする列を持つオブジェクト型address_tを作成し、最後に不完全なdept_tの定義に埋め込みます。
使用できるデータ例を次に示します。
insert into emp values(1,'John','900',100); insert into emp values(2,'james','1000',100); insert into emp values(3,'jack',2000,200);
6.13.2 循環参照を持つオブジェクト・ビューの作成
循環参照を持つオブジェクト・ビューを作成できます。
「オブジェクト・ビューにおける複雑なリレーションシップの定義」の説明に従って基礎となるリレーショナル表定義を設定した場合、その定義に基づいてオブジェクト・ビューを作成できます。
内容は次のとおりです。
6.13.2.1 方法1: 2つ目のビューを作成した後、最初のビューを再作成する
2つ目のビューを作成した後、最初のビューを再作成できます。
まず、deptref列にNULLを持つ従業員ビューを作成します。後で、その列を参照に変えることができます。
次に、従業員オブジェクトへの参照を含む部門ビューを作成します。これにより、従業員オブジェクト全体を含めるのではなく、従業員オブジェクトへの参照のリストを作成します。
次に、部門ビューへの参照を持つ従業員ビューを再作成します。
例6-11 循環参照を持つオブジェクト・ビューの作成、方法1
-- Requires Ex. 6-10
CREATE VIEW emp_view OF emp_t WITH OBJECT IDENTIFIER(eno)
AS SELECT e.empno, e.empname, e.salary, NULL
FROM emp e;
-- create department view, including references to the employee objects
CREATE VIEW dept_view OF dept_t WITH OBJECT IDENTIFIER(dno)
AS SELECT d.deptno, d.deptname,
address_t(d.deptstreet,d.deptcity,d.deptstate,d.deptzip),
CAST( MULTISET (
SELECT MAKE_REF(emp_view, e.empno)
FROM emp e
WHERE e.deptno = d.deptno)
AS employee_list_ref_t)
FROM dept d;
CREATE OR REPLACE VIEW emp_view OF emp_t WITH OBJECT IDENTIFIER(eno)
AS SELECT e.empno, e.empname, e.salary,
MAKE_REF(dept_view, e.deptno)
FROM emp e;
これでビューが作成されました。
6.13.2.2 方法2: FORCEキーワードを使用して最初のビューを作成する
他のビューがまだ存在していなくても、最初のビューを強制的に作成できます。
ビューを作成する文に構文エラーがないという確信があれば、FORCEキーワードを使用して、他のビューを存在させずに、最初のビューを強制的に作成できます。
まず、この時点で存在しない部門ビューへの参照を含む従業員ビューを作成します。部門ビューが適切に作成されるまで、このビューの問合せは実行できません。
次に、従業員オブジェクトへの参照を含む部門ビューを作成します。emp_viewがすでに存在するため、ここでFORCEキーワードを使用する必要はありません。これにより、部門ビューの問合せを実行し、ネストした表empreflistからの従業員参照を解除することで従業員オブジェクトを取得できます。
例6-12 FORCEを持つビューの作成、方法2
-- Requires Ex. 6-10
-- create employee view
CREATE OR REPLACE FORCE VIEW emp_view OF emp_t WITH OBJECT IDENTIFIER(eno)
AS SELECT e.empno, e.empname, e.salary,
MAKE_REF(dept_view, e.deptno)
FROM emp e;
-- create a department view that includes references to the employee objects
CREATE OR REPLACE VIEW dept_view OF dept_t WITH OBJECT IDENTIFIER(dno)
AS SELECT d.deptno, d.deptname,
address_t(d.deptstreet,d.deptcity,d.deptstate,d.deptzip),
CAST( MULTISET (
SELECT MAKE_REF(emp_view, e.empno)
FROM emp e
WHERE e.deptno = d.deptno)
AS employee_list_ref_t)
FROM dept d;
-- Querying with DEREF method
SELECT DEREF(e.COLUMN_VALUE)
FROM TABLE( SELECT e.empreflist FROM dept_view e WHERE e.dno = 100) e;
COLUMN_VALUEは、スカラーのネストした表の中のスカラー値を表す特別な名前です。この場合、COLUMN_VALUEはネストした表empreflistの中にある従業員オブジェクトの参照を示しています。
名前がJohnで始まるすべての従業員の従業員番号のみにアクセスすることも可能です。
例6-13 COLUMN_VALUEを使用した問合せ
-- Requires Ex. 6-10 and 6-12 SELECT e.COLUMN_VALUE.eno FROM TABLE(SELECT e.empreflist FROM dept_view e WHERE e.dno = 100) e WHERE e.COLUMN_VALUE.ename like 'John%';
表形式で出力するには、部門表をネストした表の項目と結合し、参照のリストのネストを解除します。
例6-14 COLUMN_VALUEを使用した問合せ、参照のネスト解除
-- Requires Ex. 6-10 and 6-12 SELECT d.dno, e.COLUMN_VALUE.eno, e.COLUMN_VALUE.ename FROM dept_view d, TABLE(d.empreflist) e WHERE e.COLUMN_VALUE.ename like 'John%' AND d.dno = 100;
最後に、dept_viewのかわりにemp_viewを使用するように、前述の問合せを書きなおし、ビュー間をナビゲートする方法を紹介します。
例6-15 COLUMN_VALUEを使用した問合せ、emp_viewの問合せ
-- Requires Ex. 6-10 and 6-12 SELECT e.deptref.dno, DEREF(f.COLUMN_VALUE) FROM emp_view e, TABLE(e.deptref.empreflist) f WHERE e.deptref.dno = 100 AND f.COLUMN_VALUE.ename like 'John%';