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%';