
  10年以上、オブジェクトリレーショナルDBMSが存在し、保存された情報の構造は常に複雑であり、SQL標準はオブジェクト指向プログラミング言語とのインターフェースの問題を考慮していますが、それでも、オブジェクトパラダイムをサポートする機能がデータベースで使用されることはほとんどありません。 これは、開発者の保守主義、オブジェクトリレーショナルデータベースを設計するための開発された方法論の欠如、およびORMツールの広範な使用が原因です。 ただし、データベース自体のオブジェクト機能を使用すると、システムのパフォーマンスと柔軟性が向上するタスクがいくつかあります。 
      
        
        
        
      
    
      
        
        
        
      
     そもそも、データベース自体のテーブルではなくオブジェクトにデータを保存するのはやや不快です。ほとんどの開発者はすでにORMツールの使用に慣れています。 この問題を解決する方法の1つは、テーブル構造を妨げることなく、既存のリレーショナルデータに基づいて合成されたオブジェクトを使用することです。 これはオブジェクトビューを使用して実現できます。オブジェクトビューを使用すると、テーブルから選択した属性に基づいてオブジェクトを合成できます(実際、これはサーバー側でのみ同じORMです)。 リレーショナル表現が仮想テーブルであるように、オブジェクト表現はオブジェクトの仮想テーブルです。 
      
        
        
        
      
    
      
        
        
        
      
     オブジェクトアプローチを使用することの明らかな利点に加えて、このアプローチでは、ビューを変更するだけでオブジェクトを再定義し、アプリケーションで使用可能なデータをフィルター処理し、オブジェクト階層のレベルでユーザーアクセスを制限し、特定の状況ではパフォーマンスを向上させることもできます。 オブジェクト表現は、データストレージの適用方法に制限を課さないことに注意することが重要です。OracleDBMSオプション(パーティショニング、ラベルセキュリティ、高度な圧縮など)を使用する機能、およびdlinksを介して接続されたテーブルが可能です。 
      
        
        
        
      
    
      
        
        
        
      
     以下に、Oracle DBMSに実装されたオブジェクト表現の主な機能を示します。 たとえば、図として、お店、それらを結ぶ道路、および商品のサプライヤに関する情報を格納する簡単なテーブルセットを提案します。 
      
        
        
        
      
    
      
        
        
        
      
     
      
        
        
        
      
    
      
        
        
        
      
     テーブルには、次のモデルを説明するデータが含まれています。 
      
        
        
        
      
    
      
        
        
        
      
     
      
        
        
        
      
    
      
        
        
        
      
     したがって、オブジェクト表現の作成は、3つの主要な手順で構成されます。 
      
        
        
        
      
    -  必要な属性を持つオブジェクトタイプを定義します。 
-  オブジェクトで定義されているのと同じ順序でテーブルからこれらの属性を選択するクエリを作成します。 
-  オブジェクトへの参照として使用する属性の選択から取得した一意の値を設定します(多くの場合、主キーを使用するだけで十分です)。 
     まず、ストアとストア間の関係を記述するオブジェクトを定義します。 
      
        
        
        
      
    CREATE FORCE TYPE road_t AS OBJECT ( 
      
        
        
        
      
     shop REF shop_t, 
      
        
        
        
      
     distance NUMBER(8)); 
      
        
        
        
      
     / 
      
        
        
        
      
     CREATE TYPE road_list_t AS TABLE OF road_t; 
      
        
        
        
      
     / 
      
        
        
        
      
     CREATE TYPE shop_t AS OBJECT ( 
      
        
        
        
      
     id NUMBER(6), 
      
        
        
        
      
     name VARCHAR2(20), 
      
        
        
        
      
     links road_list_t) NOT FINAL ; 
      
        
        
        
      
     /
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
     循環リンクを実装するには、FORCEディレクティブが必要でした。店舗は道路にリンクし、道路は他の店舗にリンクします。 次に、ビューを定義します。 
      
        
        
        
      
     CREATE FORCE VIEW shops_v OF shop_t WITH OBJECT IDENTIFIER(id) AS 
      
        
        
        
      
     SELECT s.id, s.name, AST(MULTISET( 
      
        
        
        
      
     SELECT MAKE_REF(shops_v, 
      
        
        
        
      
     decode(r.dest_id - s.id, 0, r.src_id, r.dest_id)), r.distance 
      
        
        
        
      
     FROM roads r WHERE s.id in (r.dest_id, r.src_id) 
      
        
        
        
      
     ) AS road_list_t) 
      
        
        
        
      
     FROM shops s; 
      
        
        
        
      
     /
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
      WITH OBJECT IDENTIFIERコンストラクトは、オブジェクトに提供される一意の識別子を設定します(この場合、shopsテーブルの主キーが使用されます)。 道路情報は店舗リンクのペアとして保存されるため、デコードコンストラクトを使用して近隣の店舗を識別します。 リンク自体は、MAKE_REF関数によって形成されます。この関数は、渡されたキーとオブジェクトテーブルまたはビューによってオブジェクトへの参照を返します。 これで、ナビゲーションバイパスを使用して、指定された店舗に隣接する店舗のリストを取得できます。 
      
        
        
        
      
     SELECT DEREF (shop).id FROM table ( SELECT links FROM shops_v WHERE id = 5); 
      
        
        
        
      
     
      
        
        
        
      
     DEREF (SHOP).ID 
      
        
        
        
      
     -------------- 
      
        
        
        
      
     1 
      
        
        
        
      
     2 
      
        
        
        
      
     6
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
      DEREF演算子は、属性から取得したリンクをリダイレクトするために使用されます-ネストされたテーブル(テーブル関数を介してアクセスされます)。 一般的なケースでは、リンクを使用すると、1対多の関係(上記を参照)と多対多の関係の両方を実装できます。次に例を示します。 
      
        
        
        
      
     CREATE FORCE TYPE vendor_shop_t UNDER shop_t 
      
        
        
        
      
     (vendors vendor_list_t); 
      
        
        
        
      
     / 
      
        
        
        
      
     CREATE FORCE TYPE vendor_list_t AS TABLE OF REF vendor_t; 
      
        
        
        
      
     / 
      
        
        
        
      
     CREATE FORCE TYPE vendor_t AS OBJECT ( 
      
        
        
        
      
     id NUMBER(3), 
      
        
        
        
      
     name VARCHAR2(10), 
      
        
        
        
      
     shops vendor_shop_list_t); 
      
        
        
        
      
     / 
      
        
        
        
      
     CREATE TYPE vendor_shop_list_t AS TABLE OF REF vendor_shop_t; 
      
        
        
        
      
     /
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
     ベンダーブランドストアvendor_shop_tを記述するオブジェクトは、shop_tからの継承によって定義されました。 オブジェクト自体と同様に、ビューは階層に配置できます。そうでない場合、ビューの定義は前のものと同様になります。 
      
        
        
        
      
     CREATE FORCE VIEW vendor_shops_v OF vendor_shop_t UNDER shops_v AS 
      
        
        
        
      
     SELECT s.id, s.name, CAST (MULTISET( 
      
        
        
        
      
     SELECT MAKE_REF(shops_v, 
      
        
        
        
      
     decode(r.dest_id - s.id, 0, r.src_id, r.dest_id)), r.distance 
      
        
        
        
      
     FROM roads r WHERE s.id in (r.dest_id, r.src_id) 
      
        
        
        
      
     ) AS road_list_t), 
      
        
        
        
      
     CAST (MULTISET( 
      
        
        
        
      
     SELECT MAKE_REF(vendors_v, vs.vendor_id) 
      
        
        
        
      
     FROM vendor_shops vs WHERE vs.shop_id = s.id 
      
        
        
        
      
     ) AS vendor_list_t 
      
        
        
        
      
     ) 
      
        
        
        
      
     FROM shops s; 
      
        
        
        
      
     / 
      
        
        
        
      
     CREATE FORCE VIEW vendors_v OF vendor_t WITH OBJECT IDENTIFIER(id) AS 
      
        
        
        
      
     SELECT v.id, v.name, CAST (MULTISET( 
      
        
        
        
      
     SELECT MAKE_REF(vendor_shops_v, vs.shop_id) 
      
        
        
        
      
     FROM vendor_shops vs WHERE vs.vendor_id = v.id 
      
        
        
        
      
     ) AS vendor_shop_list_t 
      
        
        
        
      
     ) 
      
        
        
        
      
     FROM vendors v; 
      
        
        
        
      
     /
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
     階層へのクエリを使用すると、特定のビューだけでなく、その子孫からもオブジェクトを選択できるため、詳細レベルを調整できます。 オブジェクトタイプは、ONLYおよびIS OF TYPEコンストラクトを使用して選択されます。 
      
        
        
        
      
     SELECT count (0) FROM shops_v WHERE id < 3; 
      
        
        
        
      
     
      
        
        
        
      
     COUNT (0) 
      
        
        
        
      
     -------- 
      
        
        
        
      
     4 
      
        
        
        
      
     
      
        
        
        
      
     SELECT count (0) FROM ONLY (shops_v) WHERE id < 3; 
      
        
        
        
      
     
      
        
        
        
      
     COUNT (0) 
      
        
        
        
      
     -------- 
      
        
        
        
      
     2 
      
        
        
        
      
     
      
        
        
        
      
     SELECT count (0) FROM vendor_shops_v s WHERE id < 3 AND VALUE (s) IS OF TYPE ( ONLY shop_t); 
      
        
        
        
      
     
      
        
        
        
      
     COUNT (0) 
      
        
        
        
      
     -------- 
      
        
        
        
      
     0
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
     オブジェクト表現でDMLを使用する機能の制限は、リレーショナル表現の制限に似ています。 ただし、INSTEAD OFトリガーを使用して、カスタムDMLロジックを実装できます。 次のコードは、vendors_vオブジェクトの挿入を実装し、基礎となるテーブルに情報を追加します。 
      
        
        
        
      
     CREATE TRIGGER vendors_v_insert INSTEAD OF INSERT ON vendors_v FOR EACH ROW 
      
        
        
        
      
     DECLARE 
      
        
        
        
      
     shop_id NUMBER; 
      
        
        
        
      
     CURSOR c IS SELECT DEREF (COLUMN_VALUE).id FROM table (: NEW .shops); 
      
        
        
        
      
     BEGIN 
      
        
        
        
      
     OPEN c; 
      
        
        
        
      
     INSERT INTO vendors VALUES (: NEW .id, : NEW .name); 
      
        
        
        
      
     LOOP 
      
        
        
        
      
     FETCH c INTO shop_id; 
      
        
        
        
      
     EXIT WHEN c%NOTFOUND; 
      
        
        
        
      
     INSERT INTO vendor_shops VALUES (: NEW .id, shop_id); 
      
        
        
        
      
     END LOOP ; 
      
        
        
        
      
     CLOSE c; 
      
        
        
        
      
     END ; 
      
        
        
        
      
     /
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
     表現のデータは最初はリレーショナルテーブルから取得され、インデックスなどの構築に関して制限があるという事実にもかかわらず、多くの場合、オブジェクトアプローチを使用するとパフォーマンスが向上します。 この効果は、リレーショナルアプローチで完全に表示し、オブジェクトとのリンクを操作する必要がある大量のデータとクエリで達成されることを理解することが重要です。 次のテーブルサイズと比較しました:ショップ-1000行、ベンダー-60、vendor_shops-2万、道路-30万。 例を考えてみましょう: 
      
        
        
        
      
     SELECT v1.id, v2.id 
      
        
        
        
      
     FROM vendor_shops_v v1, vendor_shops_v v2 WHERE 
      
        
        
        
      
     CARDINALITY(v1.vendors MULTISET INTERSECT v2.vendors) > 0 AND 
      
        
        
        
      
     v1.id = 2;
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
     対リレーショナルオプション 
      
        
        
        
      
     SELECT v1.id, v2.id 
      
        
        
        
      
     FROM shops v1, shops v2 WHERE 
      
        
        
        
      
     EXISTS ( 
      
        
        
        
      
     SELECT vendor_id FROM vendor_shops WHERE shop_id = v1.id 
      
        
        
        
      
     INTERSECT 
      
        
        
        
      
     SELECT vendor_id FROM vendor_shops WHERE shop_id = v2.id 
      
        
        
        
      
     ) 
      
        
        
        
      
     AND v1.id = 2;
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
     生産性が2倍に向上します。 反対に、このデータを使用して一般的なサプライヤがいる近隣の店舗のリストを取得する次のクエリのペアは、それを行わない方法の例です。 
      
        
        
        
      
     SELECT v1.id, v2.id 
      
        
        
        
      
     FROM vendor_shops_v v1, vendor_shops_v v2 
      
        
        
        
      
     WHERE v2.id in ( SELECT DEREF (shop).id FROM table (v1.links)) AND 
      
        
        
        
      
     CARDINALITY(v1.vendors MULTISET INTERSECT v2.vendors) > 0 AND 
      
        
        
        
      
     v1.id = 2; 
      
        
        
        
      
     
      
        
        
        
      
     SELECT v1.id, v2.id 
      
        
        
        
      
     FROM shops v1, shops v2 
      
        
        
        
      
     WHERE 
      
        
        
        
      
     EXISTS ( SELECT 1 FROM roads WHERE src_id=v1.id AND dest_id=v2.id) AND 
      
        
        
        
      
     EXISTS ( 
      
        
        
        
      
     SELECT vendor_id FROM vendor_shops WHERE shop_id = v1.id 
      
        
        
        
      
     INTERSECT 
      
        
        
        
      
     SELECT vendor_id FROM vendor_shops WHERE shop_id = v2.id 
      
        
        
        
      
     ) AND 
      
        
        
        
      
     v1.id = 2;
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 
      
        
        
        
      
     その結果、パフォーマンスが15倍低下します。 気づくのは難しいことではないが、その理由は、shop_tオブジェクトのlinks属性の複雑な定義にあります。これにより、road_tオブジェクトの数が2倍になり、道路テーブルからの読み取り値が比例して増加します。 どちらの例でも、オブジェクトクエリははるかに読みやすいことに注意してください。 
      
        
        
        
      
    
      
        
        
        
      
     この記事は入門的なものであるはずであったため、例を意図的に簡略化したことを予約します。 パブリケーションが応答を見つけた場合、このトピックをさらに詳しく説明します(JDBCによるオブジェクトのロードと保存、バッファリング、クラス内のメソッドの使用、Reflection APIの類似物など)。 
      
        
        
        
      
    
      
        
        
        
      
      文学 
      
        
        
        
      
    
      
        
        
        
      
      1.エリック・ベルデン、ジャニス・グリーンバーグ。  Oracle Databaseオブジェクト・リレーショナル開発者ガイド11gリリース2(11.2)-Oracle、2010年3月。PDF 
      
        
        
        
      
      2.ジム・メルトン。 高度なSQL:1999。 オブジェクトリレーショナルおよびその他の高度な機能について-Morgan Kaufmann Publishers、2003。 
      
        
        
        
      
      3. Fernstein C.階層内のオブジェクトタイプの置換と変換-Oracle Magazine / Russian Edition、2002年6月。 
      
        
        
        
      
      4. WPチャン、ノーバートリッター。 オブジェクト指向ソフトウェア開発のためのオブジェクトリレーショナルDBテクノロジーの真の利点。  B.読み取り、編集者、Proc。 データベースに関する第18回英国全国会議(BNCOD 2001)、データベースの進歩、89〜104ページ。  Springer-Verlag、2001年7月。PDF 
      
        
        
        
      
      5. S.D. クズネツォフ。 オブジェクトリレーショナルデータベース:過去の段階または過小評価された機能?、2007。HTML 
      
        
        
        
      
    
      
        
        
        
      
      ソースコードハイライターですべてのソースコードが強調表示されました。