6.14 オブジェクト・ビューの階層

オブジェクト・ビュー階層は、オブジェクト・ビューの集合で、型階層内の様々な型が、それぞれのオブジェクト・ビューの基になっています。ビュー階層内のサブビューは、型階層内のサブタイプがスーパータイプの下に作成される場合と同じ方法で、スーパービューの下に作成されます。

ビュー階層内のそれぞれのオブジェクト・ビューは、1つの型のオブジェクトと一緒に移入されますが、任意のビューについての問合せでは、そのサブビューも暗黙的に扱います。このように、オブジェクト・ビュー階層により、一定のレベルまたはそれ以上のレベルに特化されたオブジェクトの多相集合を返す問合せを、簡単に組み立てられます。

person_typをルートとする、次のような型階層について考えてみます。

図6-1 オブジェクト型階層

図6-1の説明が続きます
「図6-1 オブジェクト型階層」の説明

オブジェクト・ビューをそれぞれの型に基づいて作成し、この型階層に基づいてオブジェクト・ビュー階層を作成しておくと、目的の特化レベルと対応するオブジェクト・ビューの問合せができます。たとえば、student_typのビューについて問い合せ、学生(定時制の学生を含む)のみ入っている結果セットを取得できます。

型階層内のいずれの型も、オブジェクト・ビュー階層のルート・ビューの基として使用できます。したがって、オブジェクト・ビュー階層をルート型から始める必要はありません。また、オブジェクト・ビュー階層を型階層の各リーフまで拡張したり、すべてのブランチを範囲に入れる必要もありません。ただし、下位に介在するサブタイプは省略できません。いずれのサブビューも、直系スーパービューの型の直系サブタイプに基づく必要があります。

型が兄弟関係にあるサブタイプを複数持てるように、オブジェクト・ビューも兄弟関係にあるサブビューを複数持てます。ただし、特定の型に基づくサブビューが関与できるのは、1つのオブジェクト・ビュー階層のみです。2つの異なるオブジェクト・ビュー階層それぞれに、同じサブタイプに基づく1つのサブビューが存在することはできません。

サブビューはスーパービューからオブジェクト識別子(OID)を継承します。任意のサブビューに、OIDを明示的に指定することは許可されません。

ルート・ビューでは、WITH OBJECT ID句を使用して、オブジェクト識別子を明示的に指定できます。OIDがシステムにより生成されない場合、またはルート・ビューに句を指定しない場合は、サブビューを作成できますが、ルート・ビューがシステム生成によるOIDも使用する表またはビューに基づいている場合に限定されます。

ビューの基礎となる問合せにより、ビューが更新可能かどうかが決まります。ビューの問合せに、結合、集合演算子、集計ファンクション、GROUP BY句、DISTINCT句、疑似列または式を何も入れないというのが、ビューを更新可能にするための条件です。サブビューについても同じ条件が適用されます。

ビューが更新可能でなくても、適切なDML処理を実行するためのINSTEAD OFトリガーが定義できます。サブビューはINSTEAD OFトリガーを継承しない点に注意してください。

ビュー階層内のすべてのビューは、同じスキーマに所属する必要があります。

注意:

インスタンス化不可の型のビューを作成できます。インスタンス化不可の型はインスタンスを持つことができないため、通常、このような型のオブジェクト・ビューを作成しても意味がありません。ただし、インスタンス化不可の型は、インスタンス化可能であるサブタイプを持つことができます。インスタンス化不可の型のオブジェクト・ビューが作成できることで、インスタンス化不可の型が含まれている型階層に基づくオブジェクト・ビュー階層を得ることができます。

6.14.1 オブジェクト・ビュー階層の作成

オブジェクト・ビュー階層は、ルート・ビューの下にサブビューを作成して、構築します。このためには、例6-17のようにCREATE VIEW文でUNDERキーワードを使用します。

基礎となる様々な記憶域モデルが、同じオブジェクト・ビュー階層の基になることもあります。つまり、基礎となる表の様々なレイアウトや設計により、同じオブジェクト・ビュー階層が作成される可能性があるということです。基礎となる記憶域モデルの設計は、オブジェクト・ビュー階層のパフォーマンスや更新可能性に影響を与えます。

考えられる3種類の記憶域モデルについて説明します。最初のフラット・モデルの場合、オブジェクト・ビュー階層内のすべてのビューの基は、同じ表です。2番目の水平モデルの場合、それぞれのビューは、それぞれ別の表と1対1で対応します。3番目の垂直モデルの場合は、結合を使用してビューが構成されます。

これらの記憶域モデルを実行するには、まず例6-16に示すような型を作成します。

例6-16 記憶域モデル例に使用する型の作成

CREATE TYPE person_typ AS OBJECT
( ssn NUMBER,
  name VARCHAR2(30),
  address VARCHAR2(100)) NOT FINAL;/

CREATE TYPE student_typ UNDER person_typ 
( deptid NUMBER,
   major VARCHAR2(30)) NOT FINAL;/

CREATE TYPE employee_typ UNDER person_typ
( empid NUMBER, 
  mgr VARCHAR2(30));/

内容は次のとおりです。

6.14.1.1 フラット・モデル

フラット・モデルの場合、オブジェクト・ビュー階層内のすべてのビューの基となるのは、同じ表です。

次に例に示すAllPersonsという1つの表には、person_typstudent_typおよびemployee_typのすべての属性の列が格納されます。

図6-2 オブジェクト・ビュー階層のフラット記憶域モデル

図6-2の説明が続きます
「図6-2 オブジェクト・ビュー階層のフラット記憶域モデル」の説明

それぞれの行の型は、typeid列により識別されます。これらの有効な値は、例6-16で作成した型(1 = person_typ、2 = student_typ、 3 = employee_typ)です。

例6-17では、表AllPersonsを作成してから、オブジェクト・ビュー階層を構成するビューを作成します。

例6-17 オブジェクト・ビュー階層の作成

-- Requires Ex. 6-16
CREATE TABLE AllPersons
( typeid NUMBER(1), 
  ssn NUMBER, 
  name VARCHAR2(30), 
  address VARCHAR2(100),
  deptid NUMBER,
  major VARCHAR2(30),
  empid NUMBER, 
  mgr VARCHAR2(30));

CREATE VIEW Person_v OF person_typ
  WITH OBJECT OID(ssn) AS
  SELECT ssn, name, address 
  FROM AllPersons 
  WHERE typeid = 1;

CREATE VIEW Student_v OF student_typ UNDER Person_v
  AS 
  SELECT ssn, name, address, deptid, major
  FROM AllPersons
  WHERE typeid = 2;

CREATE VIEW Employee_v OF employee_typ UNDER Person_v
  AS
  SELECT ssn, name, address, empid, mgr
  FROM AllPersons
  WHERE typeid = 3;

フラット・モデルには単純であるという利点があり、フラット・モデルによって索引や制約への対応に支障をきたすことはありません。デメリットは次のとおりです。

  • 1つの表に格納できる列は1000以下のため、フラット・モデルでは、オブジェクト・ビュー階層に格納できる列の合計数が、1000列に制限されます。

  • 表の各列には、オブジェクト・ビューの型に属さないすべての属性のかわりにNULLが入ってしまいます。このようにNULLが後続しない状態は、パフォーマンスを低下させる可能性があります。

6.14.1.2 水平モデル

水平モデルの場合、それぞれのビューまたはサブビューの基になるのは、異なる表です。

例に示す表はリレーショナル表ですが、これらの表は、列の代入性が無効になるオブジェクト表になる場合もあります。

図6-3 オブジェクト・ビュー階層の水平記憶域モデル

図6-3の説明が続きます
「図6-3 オブジェクト・ビュー階層の水平記憶域モデル」の説明

例6-18では、表を作成してから、これらの表に基づくビューを作成します。

例6-18 表の水平モデルの作成

-- Requires Ex. 6-16 and Ex. 6-17
CREATE TABLE only_persons
( ssn NUMBER,
  name VARCHAR2(30),
  address VARCHAR2(100));

CREATE TABLE only_students
( ssn NUMBER, 
  name VARCHAR2(30),
  address VARCHAR2(100), 
  deptid NUMBER,  
  major VARCHAR2(30));

CREATE TABLE only_employees
( ssn NUMBER, 
  name VARCHAR2(30),
  address VARCHAR2(100), 
  empid NUMBER, 
  mgr VARCHAR2(30));

CREATE OR REPLACE VIEW Person_v OF person_typ
  WITH OBJECT OID(ssn) AS
  SELECT * 
  FROM only_persons; 

CREATE OR REPLACE VIEW Student_v OF student_typ UNDER Person_v
  AS 
  SELECT *
  FROM only_students;

CREATE OR REPlACE VIEW Employee_v OF employee_typ UNDER Person_v
  AS
  SELECT * 
  FROM only_employees;

水平モデルを使用すると、非常に効率的なのは、次のような構成の問合せです。

例6-19 ビューの水平モデルの問合せ

-- Requires Ex. 6-16 and Ex. 6-17
-- add the following data
insert into only_persons values(1234,'John','abc');
insert into only_students values(1111,'James','abc',100,'CS');
insert into only_employees values(2222,'jack','abc',400,'Juliet');

SELECT VALUE(p) FROM Person_v p
  WHERE VALUE(p) IS OF (ONLY student_typ);

OUTPUT:
VALUE(P)(SSN, NAME, ADDRESS)
--------------------------------------------------------------------------------
STUDENT_TYP(1111, 'James', 'abc', 100, 'CS')

このような問合せでは、特定の型のオブジェクトをすべて取得するために、1つの物理表にアクセスするだけで済みます。このモデルのデメリットは、SELECT * FROM viewのような問合せでは、基礎となるすべての表に対してUNIONを実行し、指定されたビューの列に対してのみ行を投影する必要があることです。また、属性(および一意制約)についての索引は複数の表をまたがる必要がありますが、現在これはサポートされていません。

6.14.1.3 垂直モデル

垂直モデルの場合、階層内のそれぞれのビューと対応する物理表が存在します。

しかし、物理表に格納されるのは、対応するサブタイプに固有の属性のみです。

図6-4 オブジェクト・ビュー階層の垂直記憶域モデル

図6-4の説明が続きます
「図6-4 オブジェクト・ビュー階層の垂直記憶域モデル」の説明

例6-20では、表を作成してから、対応するビューを作成します。

例6-20 表およびビューの垂直モデルの作成

CREATE TABLE all_personattrs 
( typeid NUMBER,
  ssn NUMBER,  
  name VARCHAR2(30),
  address VARCHAR2(100));

CREATE TABLE all_studentattrs
( ssn NUMBER, 
  deptid NUMBER, 
  major VARCHAR2(30));

CREATE TABLE all_employeeattrs
( ssn NUMBER,
  empid NUMBER, 
  mgr VARCHAR2(30));

CREATE OR REPLACE VIEW Person_v OF person_typ 
WITH OBJECT OID(ssn) AS
  SELECT ssn, name, address 
  FROM all_personattrs 
  WHERE typeid = 1;

CREATE OR REPLACE VIEW Student_v OF student_typ UNDER Person_v
  AS 
  SELECT x.ssn, x.name, x.address, y.deptid, y.major
  FROM all_personattrs x, all_studentattrs y
  WHERE x.typeid = 2 AND x.ssn = y.ssn;

CREATE OR REPLACE VIEW Employee_v OF employee_typ UNDER Person_v
  AS
  SELECT x.ssn, x.name, x.address, y.empid, y.mgr
  FROM all_personattrs x, all_employeeattrs y
  WHERE x.typeid = 3 AND x.ssn = y.ssn;

垂直モデルでは、SELECT * FROM root_viewのような問合せが効率的に処理される他、個々の属性に索引を付けたり、属性に一意制約を付けることができます。ただし、型のインスタンスを再作成するには、それぞれのレベルについて、階層のルートから型を削除するオブジェクト識別子(OID)の結合を実行する必要があります。

6.14.2 階層内のビューの問合せについて

オブジェクト・ビュー階層内の任意のビューまたはサブビューに対し、問合せを実行できます。

問合せにより戻されるのは、問い合せたビューの宣言された型の行と、その型のサブタイプの行です。

たとえば、person_typ型階層が基になっているオブジェクト・ビュー階層では、person_typのビューを問い合せて、学生や従業員を含む個人全員が格納されている結果セットを取得したり、student_typのビューを問い合せて、学生(定時制の学生を含む)のみ格納されている結果セットを取得できます。

問合せのSELECT構文のリストには、オブジェクト・インスタンスを戻すREF()VALUE()のようなファンクションを含めるか、またはperson_typnamessn属性のようなビューの宣言された型のオブジェクト属性を指定できます。

オブジェクト・インスタンスを戻すためにファンクションを指定すると、問合せにより多相結果セットが戻されます。つまり、ビューの宣言された型のインスタンスと、その型のサブタイプのインスタンスのどちらも戻されます。

たとえば、次の問合せでは、あらゆる型の個人、従業員および学生のインスタンスのみでなく、これらのインスタンスREFも戻されます。

例6-21 REFと値での問合せ

-- Requires Ex. 6-20
insert into all_personattrs values(1,1111,'John','abc');
insert into all_personattrs values(2,2222,'Jack','def');
insert into all_personattrs values(3,3333,'James','ghi');
insert into all_studentattrs values(2222,100,'CS');
insert into all_employeeattrs values(3333,444,'Julia');
SELECT REF(p), VALUE(p) FROM Person_v p;

OUTPUT:
REF(P)
--------------------------------------------------------------------------------
VALUE(P)(SSN, NAME, ADDRESS)
--------------------------------------------------------------------------------
00004A038A00465A6E6E779EC1F25FE040578CE70A447E0000001426010001000100290000000000
090600812A00078401FE0000000B03C20C0C00000000000000000000000000000000000000
PERSON_TYP(1111, 'John', 'abc')
 
00004A038A00465A6E6E779EC1F25FE040578CE70A447E0000001426010001000100290000000000
090600812A00078401FE0000000B03C2222200000000000000000000000000000000000000
EMPLOYEE_TYP(3333, 'James', 'ghi', 444, 'Julia')
 
00004A038A00465A6E6E779EC1F25FE040578CE70A447E0000001426010001000100290000000000
 
REF(P)
--------------------------------------------------------------------------------
VALUE(P)(SSN, NAME, ADDRESS)
--------------------------------------------------------------------------------
090600812A00078401FE0000000B03C2171700000000000000000000000000000000000000
STUDENT_TYP(2222, 'Jack', 'def', 100, 'CS')

ビューの宣言された型の個々の属性をSELECT構文のリストに指定した場合、またはSELECT *を実行した場合も、ビューの宣言された型およびこの型のサブタイプの行が戻されます。ただし、これらの行が投影される先は、ビューの宣言された型の属性の列で、使用されるのは、これらの列のみです。つまり、サブタイプを表現する対象は、ビューの宣言された型からサブタイプが継承した属性、およびサブタイプがビューの宣言された型と共有する属性のみです。

たとえば、次の問合せでは、個人全員の行およびあらゆる型の従業員および学生の行が戻されますが、結果に使用されるのは、person_typの属性(namessnおよびaddress)の列のみです。student_typdeptid属性などサブタイプに追加された属性の行は、何も表示されません。

SELECT * FROM Person_v;

結果からサブビューを除外するには、ONLYキーワードを使用します。ONLYキーワードにより、選択対象が、問合せ対象のビューの宣言された型に限定されます。

SELECT VALUE(p) FROM ONLY(Person_v) p;

6.14.3 ビュー階層についての操作の権限

通常、サブビューを持つビューについての問合せで要求されるのは、参照対象のビューについてのSELECT権限のみで、サブビューについての明示的な権限は要求されません。

次に示す問合せでは、Person_vについてのSELECT権限のみ要求され、このビューのサブビューについての権限は要求されません。

SELECT * FROM Person_v;

ただし、サブタイプの属性として追加されていても、ルート型では使用しない属性を選択する問合せの場合は、サブビューについてのSELECT権限も要求されます。このようなサブタイプ属性には、別のアクセス権限を適度に必要とする機密情報が格納されている可能性があります。

たとえば、次に示す問合せでは、オブジェクト・インスタンスが選択され、その結果、サブタイプのすべての属性が取り出されるため、Person_vStudent_vEmployee_v(およびPerson_vの他のサブビュー)についてのSELECT権限が要求されます。

SELECT VALUE(p) FROM Person_v p;

ビュー階層全体についてのSELECT権限を付与する処理を簡素化するには、HIERARCHYオプションが使用できます。ビューについてのSELECT権限をユーザーに付与するときに、HIERARCHYオプションを指定すると、現在および将来存在するビューのすべてのサブビューについてのSELECT権限も暗黙的に付与されます。次に例を示します。

GRANT SELECT ON Person_v TO user WITH HIERARCHY OPTION;

サブビューに属する行を除外する問合せには、すべてのサブビューについてのSELECT権限も要求されます。その理由は、インスタンスの最も狭い意味での型にのみ属している行の情報は、機密情報の可能性があり、すべての行をサブビューから除外する問合せ(次に示すような問合せ)の場合は、サブビューについてのSELECT権限が要求されるためです。

SELECT * FROM ONLY(Person_v);