7.2 型の依存性

型依存性は大きく次の2つのカテゴリに分かれます。

  • 型が定義に対して相互に依存し、一方の型が他方の型の定義の一部である可能性がある状況。

  • 型の作成または削除が表や型などの型が持つ依存性によって複雑になる状況。

この項の内容は次のとおりです。

7.2.1 不完全な型の作成

直接的または中間の型を介して定義に対して互いに依存する型を、相互依存といいます。たとえば、employeeの1つの属性を従業員が属する部門にし、departmentの1つの属性を部門を管理する従業員にするように、オブジェクト型employeeおよびdepartmentを定義できます。

矢印を使用して一連の相互依存型の関係を示す図を視覚化する場合、つながりがループを形成します。そのような循環依存を定義するには、サークルの最小限1つのセグメントにREFを使用する必要があります。

たとえば、例7-7に示す型を定義できます。

例7-7 依存オブジェクト型の作成

-- Requires Ex. 7-1 and password
CONNECT user1
-- Enter password
ALTER SESSION SET PLSQL_WARNINGS = 'enable:all';

CREATE TYPE department; // a placeholder
/

CREATE TYPE employee AS OBJECT (
  name    VARCHAR2(30),
  dept    REF department,
  supv    REF employee );
/

CREATE TYPE emp_list AS TABLE OF employee;
/

CREATE TYPE department AS OBJECT (
  name    VARCHAR2(30),
  mgr     REF employee,
  staff   emp_list );
/

これは、適切な相互依存型におけるSQL DDL文の適切な順序です。これをエラーなしでコンパイルします。

例7-7のコードはdepartment型を2回作成することに注意してください。最初の文は、employeeREF属性が指すプレースホルダとして機能するdepartmentの不完全な宣言です。AS OBJECT句が省略され、属性またはメソッドがリストされていない点で、この宣言は不完全です。これらは、後述の型を完成させる完全な宣言で指定します。ここでは、departmentを不完全なオブジェクト型として作成しておきます。これにより、employeeがエラーなしでコンパイルできます。

不完全な型をプレースホルダとして作成しない場合、その型を参照する型はコンパイルされますが、コンパイル・エラーが発生します。たとえば、departmentが存在しない場合、それを不完全な型として作成し、employeeはコンパイル・エラーになります。この場合、次回なんらかの操作がこの型にアクセスする際に、employeeが再コンパイルされます。この型が依存するすべての型が作成され、その依存性が完全な場合、エラーなしでコンパイルされます。

不完全な型を使用することにより、まだ作成されていないサブタイプに対するREF属性を格納する型も作成できます。こうしたスーパータイプを作成するには、参照するサブタイプの不完全な型を最初に作成します。完全なサブタイプは、スーパータイプ作成後に作成します。

7.2.2 不完全な型の再定義

不完全な型が参照するすべての型を作成したら、不完全な型が不完全な状態を維持する必要がなくなるため、不完全な型の宣言を再定義してください。

型を再定義すると、型が再コンパイルされ、システムが様々なロックを解放できるようになります。型は、CREATE TYPE文を使用して再定義します。

  • 例7-7の最後に示すとおり、型の属性およびメソッドを指定するCREATE TYPE文を実行します。

データベースによって作成される不完全な型も再定義する必要があります。前述の項で説明したように、不完全な型としてdepartmentを明示的に作成しなかった場合、データベースによって作成されました。この場合、引き続き再定義する必要があります。

不完全なオブジェクト型は、オブジェクト型として再定義する必要があります。オブジェクト型をコレクション型(ネストした表型または配列型)として再定義することはできません。その型を削除することはできます。

7.2.3 手動による型の再コンパイル

型の作成でコンパイル・エラーが発生し、その型に対してなんらかの操作(表の作成、行の挿入など)を実行しようとした場合、エラーが発生することがあります。この操作を行う前に、タイプを再コンパイルする必要があります。ALTER TYPE文を使用して再コンパイルします。

  • ALTER TYPE typename COMPILE文を実行します。型のコンパイルが正常に実行された後、操作を再試行してください。

7.2.4 型および表の依存性がある場合のCREATE OR REPLACE TYPEの使用

CREATE OR REPLACE TYPE文は、置換される型に表または型の依存性がある場合にエラーをスローします。これは、オブジェクト、VARRAYおよびネストした表の型に適用されます。また、継承または型の合成(一方の型をもう一方の型に埋め込む)に関連する型の依存性にも適用されます。継承または型の合成では、一方の型がもう一方の属性である場合があります。

CREATE OR REPLACE TYPE文でFORCEオプションを使用すると、型の依存性がある場合に型を置換できますが、表の依存性がある場合には置換できません。表の依存性はエラーの原因になります。

  • 型の依存性がある場合は、FORCEオプションをCREATE OR REPLACE TYPE文で使用して型を置換します。

例7-8に、型の依存性が原因で失敗するCREATE OR REPLACE文を示します。

例7-8 CREATE OR REPLACEの型と表のエラー

SQL> CREATE type t1 AS OBJECT (a number) not final;
  2  /
Type created.
 
SQL> CREATE TYPE t2 UNDER t1 (b varchar(10));
  2  /
Type created.
 
SQL> CREATE OR REPLACE TYPE t1 AS OBJECT (c varchar(20));
  2  /
CREATE OR REPLACE TYPE t1 AS OBJECT (c varchar(20));
*
ERROR at line 1:
ORA-02303: cannot drop or replace a type with type or table dependents

7.2.5 FORCEを指定した型の作成または置換

表の依存性を持つ型は置換できないため、型に表の依存性がある場合、CREATE OR REPLACE FORCE文は失敗します。

例7-9に、CREATE OR REPLACE FORCE文が型の依存性を持つ型の置換に続いて親の型を使用した表の作成に成功するコードを示します。ただし、最後のCREATE OR REPLACE FORCE文は、型に表の依存性があり、FORCEオプションを使用しても表の依存性を持つ型は置換できないため、失敗します。

関連項目:

SQL文CREATE OR REPLACE TYPEの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

例7-9 FORCEを指定したCREATE OR REPLACE

SQL> CREATE OR REPLACE TYPE t1 FORCE AS OBJECT (c varchar(20));
  2  /
Type created.
 
SQL> CREATE TABLE tb1 (c1 t1);
Table created.
 
SQL> CREATE OR REPLACE TYPE t1 FORCE AS OBJECT (d number);
  2  /
CREATE OR REPLACE TYPE t1 FORCE AS OBJECT (d number);
*
ERROR at line 1:
ORA-22866: cannot replace a type with table dependents

7.2.6 代入可能な表および列の型依存性

特定の型の代入可能な表または列は、その型のみでなく型のすべてのサブタイプも依存します。

それは、型のサブタイプで追加されたそれぞれの属性について、非表示列が表に追加されることからもわかります。代入可能な表または列に、このサブタイプのデータが何も入っていない場合も、非表示列は追加されます。

例7-10では、型person_typpersons表は、person_typのみでなく、person_typのサブタイプであるstudent_typおよびpart_time_student_typにも依存します。

依存型、表または列を持つサブタイプを削除しようとすると、DROP TYPE文はエラーを戻し、異常終了します。したがって、part_time_student_typは、persons表に依存しているので、削除しようとすると、エラーとなります。

依存表または依存列が存在しても、削除する型のデータが何も入っていない場合は、VALIDATEキーワードを使用して、型を削除できます。VALIDATEキーワードが使用されていると、指定された型のインスタンスが実際に格納されているかどうかを調べ、何も見つからなければ、型を削除します。型に固有の属性と関連付けられた非表示列も削除されます。

例7-10で、part_time_student_typに依存表(persons)があるため、最初のDROP TYPE文に失敗します。ただし、personspart_time_student_typのインスタンスが何も入っていなければ(および他の依存表または依存列のいずれも入っていなければ)、VALIDATEキーワードにより2番目のDROP TYPE文は正常に実行されます。

例7-10 VALIDATEを使用するおよび使用しないDROP TYPE

CREATE TYPE person_typ AS OBJECT (
  idno           NUMBER,
  name           VARCHAR2(30),
  phone          VARCHAR2(20))
  NOT FINAL;
/
CREATE TYPE student_typ UNDER person_typ (
    dept_id NUMBER,
    major VARCHAR2(30))
NOT FINAL;
/
CREATE TYPE part_time_student_typ UNDER student_typ (number_hours NUMBER);
/
CREATE TABLE persons OF person_typ;
-- Following generates an error due to presence of Persons table 
DROP TYPE part_time_student_typ -- incorrect statement;
-- Following succeeds if there are no stored instances of part_time_student_typ
DROP TYPE part_time_student_typ VALIDATE;

注意:

サブタイプの削除中に、VALIDATEオプションを使用することをお薦めします。

関連項目:

代入性の詳細な説明は、「型階層内の型の代入」を参照してください

7.2.7 DROP TYPE FORCEオプション

DROP TYPE文にはFORCEオプションがあり、型に依存型または依存表がある場合でも、型が削除されます。

存在するすべての依存型または依存表に無効のマークが付けられ、型が削除されるとアクセス不能になるので、FORCEオプションは慎重に使用します。この理由で無効のマークが付けられた表のデータに、再びアクセスすることはできません。こうした表に対して実行できる操作は、削除のみです。

関連項目:

型の変更方法の詳細は、「型進化」を参照してください。