このマニュアルの前の章では、Oracleオブジェクトで作業を開始するために必要なトピックについて説明しています。この章では、オブジェクト・リレーショナル技法を大規模なアプリケーションまたは複雑なスキーマに適用する場合について説明します。
内容は次のとおりです。
Oracleデータベースは、オブジェクト型の複合構造を、記憶域に対する単純な表構造に自動的にマップします。
関連する内容は次のとおりです。
オブジェクト型はツリー構造に似ており、ブランチが属性を表します。それ自体がオブジェクトである属性は、それ自体の属性でサブブランチを発生させます。
最終的に、各ブランチの終わりは、組込み型(NUMBER
、VARCHAR2
、REF
など)またはコレクション型(VARRAY
、ネストした表など)の属性になります。元のオブジェクト型のこのようなリーフ・レベル属性は、それぞれ表の列に格納されます。
コレクション型ではないリーフ・レベル属性は、オブジェクト型のリーフ・レベル・スカラー属性と呼ばれます。
次の内容は、「オブジェクトを表に格納する方法」のオブジェクト表およびリレーショナル表の説明に関連しています。
オブジェクト表では、すべてのリーフ・レベル・スカラー属性またはREF
属性に対するデータが、個々の列に格納されます。
注意: 各VARRAY も、大きすぎないかぎり、列に格納されます。ネストした表型のリーフ・レベル属性は、オブジェクト表に対応付けられた個々の表に格納されます。これらの表は、オブジェクト表宣言の一部として宣言する必要があります。「VARRAYの内部レイアウト」および「ネストした表の内部レイアウト」を参照してください。 |
オブジェクト表にある行オブジェクトの属性を取り出したり、変更する場合、対応する操作が表の列で実行されます。行オブジェクト自体の値にアクセスすると、オブジェクト表の列を引数として使用し、その型のデフォルトのコンストラクタを起動して、オブジェクトのコピーを生成します。
システムによって生成されたオブジェクト識別子は、非表示列に格納されます。オブジェクト識別子を使用して、そのオブジェクトに対するREF
を作成します。
表(リレーショナル表)がオブジェクト型の列とともに定義されている場合、オブジェクト型のリーフ・レベル属性に対する表に、非表示列が追加されます。オブジェクト型の各列には、その列オブジェクトのNULL情報(トップレベルのオブジェクトおよびネストしたオブジェクトのアトミックNULL)を格納するための非表示列があります。
代入可能な列またはオブジェクト表には、その列のオブジェクト型の各属性に対してのみでなく、そのオブジェクト型のサブタイプに追加された各属性に対しても、非表示列があります。これらの列には、代入可能な列に挿入されたサブタイプのインスタンスに対する属性の値が格納されます。
型判別式の列およびNULLイメージ列以外に、次の列が例8-1で作成されるperson_typ
の代入可能な列に関連付けられます。
person_typ
の各属性の非表示列: idno
、name
およびphone
person_typ
のサブタイプの属性の非表示列
したがって、student_typ
に対する属性dept_id
とmajor
およびpart_time_student_typ
に対する属性number_hours
がperson_typ
の代入可能な列に関連付けられる場合があります。
サブタイプを作成する場合、サブタイプの新しい属性の非表示列が、その新しいサブタイプの祖先クラスの代入可能な列を含む表に自動的に追加されます。追加された非表示列は、表にレトロフィットして、新しい型のデータを格納できるようになります。なんらかの理由で、非表示列を追加できない場合は、そのサブタイプの作成はロールバックされます。
VALIDATE
オプションとともにDROP TYPE
を使用してサブタイプを削除すると、データを含まないサブタイプの固有の属性に対する非表示列は、自動的に削除されます。これらの列にデータが含まれる場合、エラーが発生します。
例8-1では、この章の後続の例に必要な型を作成します。
例8-1 型の作成および表への挿入
-- drop any of these objects created for Ex.7-10 CREATE TYPE person_typ AS OBJECT ( idno NUMBER, name VARCHAR2(30), phone VARCHAR2(20), MAP MEMBER FUNCTION get_idno RETURN NUMBER ) NOT FINAL; / CREATE TYPE BODY person_typ AS MAP MEMBER FUNCTION get_idno RETURN NUMBER IS BEGIN RETURN idno; END; END; / 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 TYPE employee_typ UNDER person_typ ( emp_id NUMBER, mgr VARCHAR2(30)); / CREATE TABLE person_obj_table OF person_typ; // an object table INSERT INTO person_obj_table VALUES (person_typ(12, 'Bob Jones', '650-555-0130')); INSERT INTO person_obj_table VALUES (student_typ(51, 'Joe Lane', '1-650-555-0140', 12, 'HISTORY')); INSERT INTO person_obj_table VALUES (part_time_student_typ(52, 'Kim Patel', '1-650-555-0135', 14, 'PHYSICS', 20));
代入可能な列は、非表示の型判別式の列に関連付けられます。非表示列には、型IDと呼ばれる識別子があり、この識別子によって、代入可能な列中の各オブジェクトのうち、最も具体的な型が識別されます。通常、型ID(RAW
)は1バイトですが、大きな階層の場合は最大4バイトまでとなります。
指定されたオブジェクト・インスタンスの型IDは、ファンクションSYS_TYPEID
を使用して特定できます。
例8-2では、例8-1で作成される代入可能なオブジェクト表に格納されるオブジェクト・インスタンスの型IDを取り出します。
例8-2 表に格納されるオブジェクトの型IDの問合せ
-- Requires Ex. 8-1
SELECT name, SYS_TYPEID(VALUE(p)) typeid
FROM person_obj_table p;
NAME TYPEID
------------------------------ ---------------------------
Bob Jones 01
Joe Lane 02
Kim Patel 03
カタログ・ビューのUSER_TYPES
、DBA_TYPES
およびALL_TYPES
には、各型に対する型ID値を与えるTYPEID
列(非表示ではない)があります。この列に対して結合を実行して、型判別式の列にある型IDに対応する型名を取得できます。
データベースが行オブジェクトに対してREF
を作成する場合、その作成されるREF
は、オブジェクト識別子(OID)、オブジェクト表のいくつかのメタデータ、およびROWID
(オプション)で構成されます。
REF
型の列にあるREF
のサイズは、次のその列に対応付けられた記憶域要件に依存します。
列がREF
WITH
ROWID
として宣言されている場合、ROWID
はREF
列に格納されます。ROWID
のヒントは、制約付きREF
列にあるオブジェクト参照では無視されます。
列がSCOPE
句を使用してREF
として宣言されている場合、オブジェクト表のメタデータおよびROWID
の省略によって、その列は少なくなります。有効範囲付きREF
の長さは、16バイトです。
オブジェクト識別子が主キー・ベースの場合、主キーを導出する列の数に基づいて、主キーの値を格納するための1つ以上の内部列が作成されます。
注意: オブジェクト識別子が主キーから導出される行オブジェクトをREF 列が参照する場合、このREF列を、主キー・ベースREF またはpkREF といいます。pkREF を含む列は、有効範囲付きであるかまたは参照制約が指定されている必要があります。 |
ネストした表の行は、別の記憶表に格納されます。ネストした表には、列ごとに1つの記憶表が対応付けられています。記憶表は、その列にあるすべてのネストした表に対するすべての要素を保持しています。記憶表には、システム生成の値を持つ非表示のNESTED_TABLE_ID
列があり、この値によって、Oracle Databaseでは、ネストした表の要素が適切な行にマップされます。
記憶表を索引構成表にすることによって、コレクション全体を取り出す問合せを高速化できます。ORGANIZATION INDEX
句をSTORE AS
句の中に挿入します。
「ネストした表の記憶域」を参照してください。
ネストした表型は、オブジェクトまたはスカラーを含むことができます。
要素がオブジェクトである場合、記憶表はオブジェクト表のようになります。つまり、そのオブジェクト型のトップレベルの属性が記憶表の列となります。ただし、ネストした表の行にはオブジェクト識別子列がないため、ネストした表のオブジェクトに対してREF
は作成できません。
要素がスカラーである場合、記憶表には、スカラー値を含むCOLUMN_VALUE
という単一の列が含まれます。
VARRAY
のすべての要素は、単一の列に格納されます。配列のサイズに基づいて、インラインまたはBLOB
に格納されます。詳細は、「VARRAYの記憶域上の考慮点」を参照してください。
この項では、型IDおよび属性での索引の使用方法を説明します。
この項の内容は次のとおりです。
SYS_TYPEID
ファンクションを使用して、代入可能な列の非表示の型判別式の列に索引を作成できます。型判別式の列には、型IDがあり、この識別子によって、代入可能な列中の各オブジェクト・インスタンスのうち、最も具体的な型が識別されます。この情報は、IS OF
述語を使用して型に基づいてフィルタにかける問合せの評価に使用されるものですが、SYS_TYPEID
ファンクションを使用して独自の目的で型IDにアクセスすることも可能です。
一般に、型判別式の列には、わずかな数の型IDのみが格納されています。関連のある型階層に含まれている型の数を超えることはありません。この列はカーディナリティが低いので、ビットマップ索引の作成に適しています。
たとえば、次の文では、表contacts
の代入可能なcontact
列の基礎となる型判別式の列のビットマップ索引を作成します。ファンクションSYS_TYPEID
は、型判別式の列を参照します。
例8-3 代入可能な列のビットマップ索引の作成
-- Requires Ex. 8-1 CREATE TABLE contacts ( contact person_typ, contact_date DATE ); INSERT INTO contacts VALUES ( person_typ (65,'Vrinda Mills', '1-650-555-0125'),'24 Jun 2003' ); INSERT INTO contacts VALUES ( person_typ (12, 'Bob Jones', '650-555-0130'),'24 Jun 2003' ); INSERT INTO contacts VALUES ( student_typ(51, 'Joe Lane', '1-650-555-0140', 12, 'HISTORY'),'24 Jun 2003' ); INSERT INTO contacts VALUES ( part_time_student_typ(52, 'Kim Patel', '1-650-555-0135', 14, 'PHYSICS', 20),'24 Jun 2003' ); CREATE BITMAP INDEX typeid_idx ON contacts (SYS_TYPEID(contact));
代入可能な列内に格納できる任意の型の属性に対して索引を作成できます。サブタイプの属性は、TREAT
ファンクションを使用して求めるサブタイプ(およびそのサブタイプ)以外の型をフィルタにかけて排除することによってCREATE INDEX
文で参照できます。その後、ドット表記によって、希望の属性を指定します。
たとえば、次の文では、contacts
表にある、すべての学生のmajor
属性に対する索引が作成されます。contact
列の宣言された型はperson_typ
で、student_typ
がそのサブタイプであるため、この列にはperson_typ
、student_typ
のインスタンスおよびいずれかのサブタイプを格納できます。
例8-4 すべての学生の属性に対する索引の作成
-- Requires Ex.8-1- and 8-3 CREATE INDEX major1_idx ON contacts (TREAT(contact AS student_typ).major);
student_typ
は、最初にmajor
属性を定義しました。person_typ
スーパータイプにはこの型はありません。したがって、major
属性に対する非表示列のすべての値は、個人の型student_typ
またはparttimestudent_typ
(student_typ
サブタイプ)に対する値です。つまり、非表示列の値は、学生のサブタイプも含めてすべての学生のmajor
の値のTREAT
式によって戻される値と同一であることを意味しています。つまり、非表示列も、TREAT
式もともに、学生については専攻を、学生以外についてはNULLをリストします。このことを利用して、非表示列に対する索引major1_idx
が、通常のBツリー索引として作成されます。
非表示列の値が、前述のように、TREAT
式によって戻される値と同一になるのは、TREAT
ファンクションのターゲットとして指定された型(student_typ
)が最初にそのmajor
属性を定義した型である場合にかぎります。TREAT
ファンクションのターゲットが、次の例のように、単にその属性を継承するサブタイプである場合は、TREAT
式は、サブタイプ(定時制の学生)に対してはNULL以外のmajor
値を戻しますが、スーパータイプ(その他の学生)に対しては非NULLは戻しません。
CREATE INDEX major2_idx ON contacts (TREAT(contact AS part_time_student_typ).major);
この場合、非表示列にmajor
の値として格納されている値は、TREAT
式の結果とは異なっている場合があります。したがって、通常のBツリー索引を基礎となる列に対して作成することはできません。したがって、データベースでは、TREAT
式は他のすべてのファンクション・ベースの式と同様に処理され、索引を、結果に対するファンクション索引として作成する試みが行われます。
次の例では、前述の例と同様に、定時制の学生のmajor
属性に対してファンクション索引を作成しますが、この例では、major
の非表示列は、代入可能なオブジェクト表person_obj_table
に対応付けられています。
CREATE INDEX major3_idx ON person_obj_table p (TREAT(VALUE(p) AS part_time_student_typ).major);
型進化は、オブジェクト型を変更するプロセスです。オブジェクト型は、次の方法で変更できます。
属性の追加および削除
メソッドの追加および削除
長さ、精度または位取りを引き上げるための数値属性の修正
文字長を長くするための可変長文字属性の修正
型のFINAL
およびINSTANTIABLE
プロパティの変更
VARRAY
の制限およびサイズの変更
コレクション要素の長さ、精度およびスケールの変更
型を変更すると、その型を参照する項目にも影響します。たとえば、新しい属性を型に追加する場合、その新しい属性を追加できるように、その型の列にあるデータを提示する必要があります。
この項の内容は次のとおりです。
型の依存スキーマ・オブジェクトは、型を直接的または間接的に参照し、その型に加えられた変更に影響されるオブジェクトです。
型は、次の依存スキーマ・オブジェクトを持つことができます。表、型またはサブタイプ、プロシージャ、ファンクション、パッケージ、トリガーなどのプログラム・ユニット(PL/SQLブロック)、索引タイプ、ビュー(オブジェクト・ビューを含む)、ファンクション索引、演算子。
依存スキーマ・オブジェクトが型の変更によってどのような影響を受けるかは、オブジェクトによって、また、変更の性質によって異なります。
依存プログラム・ユニット、ビュー、演算子および索引タイプは、型が変更されると、無効としてマークされます。これらの無効となったスキーマ・オブジェクトのいずれかが次回参照されると、新しい型の定義を使用して再検証されます。オブジェクトの再コンパイルが成功すると、そのオブジェクトは有効となり、再度使用できるようになります。
型の変更によっては、依存ファンクション索引が削除または無効化され、再構築が必要です。
依存表には、属性の型に応じて型に加えられた各属性に対して表に1つ以上の内部列が追加されます。新しい属性が追加される際は、NULL
値が設定されます。削除された各属性に対応付けられている列は削除されます。変更された各属性に対応付けられた長さ、精度またはスケールも、変更内容に対応して変更されます。
これらの変更は、主に表のメタデータの更新を含み、迅速に実行できます。さらに、このような表データは、「データを更新するオプション」で説明するように、型の新しいバージョンの形式に合せた更新も必要です。
更新は、データの量によっては時間がかかる場合があるため、ALTER TYPE
コマンドにオプションが用意されています。このオプションによって、すべての依存表データを即時変換するか、元の形式のままにしておいて、更新のたびに少しずつ変換するかを選択できます。
ALTER TYPE
のCASCADE
オプションは、型の変更を依存型および依存表に伝播します。「型進化に使用するALTER TYPE文」を参照してください。CASCADE
自体に、伝播の一環として表データを新しい型形式に変換するかどうかを選択できる次のオプションがあります。
INCLUDING TABLE DATA
: データを変換します(デフォルト)
NOT INCLUDING TABLE DATA
: データを変換しません
デフォルトでは、CASCADE
オプションはデータを変換します。いずれの場合も、表データは常に最新バージョンの型の形式で戻されます。表データが以前の型バージョンの形式で保存されている場合は、データが実際に保存されている形式はデータが再書込みされないかぎり変更されないにしても、そのデータは、戻される前に最新バージョンの形式に変換されます。
最新の型の定義は、システム・ビューUSER_SOURCE
から取り出せます。USER_TYPE_VERSIONS
ビューで、ある型のすべてのバージョンの定義を参照できます。
関連項目: 型の定義および型本体のコンパイルの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
型に対する構造的な変更が依存データに影響し、データの変換を必要とします。これは、ある型のメソッドの定義や動作(実装)に限定された変更には適用されません。
型に対する次の変更は構造的変更です。
属性の追加または削除
属性の長さ、精度、スケールの変更
FINAL
からNOT FINAL
に(またはその逆に)型のファイナリティを変更します
このような変更の結果、変更された型およびそのすべての依存型のバージョンが新しいバージョンになり、新しいバージョンへの変更のプロセスの一環として、依存表の内部列が追加、削除または変更されます。
これらのいずれかの変更を、依存型または依存表を持つ型に対して実行すると、変更を伝播した影響は、メタデータのみでなく、データ記憶域の構成にも影響し、データの変換を必要とします。
データの変換以外にも、変更すべき項目がある場合があります。たとえば、新しい属性が型に追加されて、その型が、その型のコンストラクタをコールする場合、型本体の各コンストラクタは、新しい属性に対する値を指定するように修正する必要があります。同様に、新しいメソッドが追加される場合は、型本体を置換して、新しいメソッドの実装を追加する必要があります。型本体は、CREATE OR REPLACE TYPE BODY
文を使用して変更できます。
例8-5に、ある属性を追加し、別の属性を削除することによってperson_typ
に単純な変更を加える方法を示します。CASCADE
キーワードは、型の変更を依存型および依存表に伝播しますが、NOT
INCLUDING
TABLE
DATA
句によって関連するデータの変換が阻止されています。
例8-5 属性の追加および削除によるオブジェクト型の変更
-- Drop person_typ and person_obj_table if they exist CREATE TYPE person_typ AS OBJECT ( idno NUMBER, name VARCHAR2(30), phone VARCHAR2(20)); / CREATE TABLE person_obj_table OF person_typ; INSERT INTO person_obj_table VALUES (person_typ(12, 'Bob Jones', '650-555-0130')); SELECT value(p) FROM person_obj_table p;
VALUE(P)(IDNO, NAME, PHONE)
--------------------------------------------
PERSON_TYP(12, 'Bob Jones', '650-555-0130')
次のように電子メール属性を追加し、電話属性を削除できます。
ALTER TYPE person_typ ADD ATTRIBUTE (email VARCHAR2(80)), DROP ATTRIBUTE phone CASCADE NOT INCLUDING TABLE DATA;
次に、型の変更に対応するために切断して再接続します。
connect oe/oe; connect hr/hr; ALTER SESSION SET PLSQL_WARNINGS = 'enable:all'; -- The data of table person_obj_table has not been converted yet, but -- when the data is retrieved, Oracle returns the data based on -- the latest type version. The new attribute is initialized to NULL. SELECT value(p) FROM person_obj_table p;
VALUE(P)(IDNO, NAME, EMAIL)
---------------------------------
PERSON_TYP(12, 'Bob Jones', NULL)
SELECT
文では、列データが最新の型バージョンに変換されている可能性があるとしても、変換されたデータが列に再度書き込まれることはありません。ある表の特定のユーザー定義型の列が頻繁に取り出される場合、データ変換が重複して行われないようにするため、そのデータを最新の型バージョンに変換することを検討してください。変換は、列にオブジェクトやネストした表列より変換に必要な時間が通常長くなるVARRAY
属性が含まれている場合、特に大きな効果があります。
前のコードと関連していない次のコード・スニペットに示すように、UPDATE
文を発行して列をそれ自体に設定し、データの列を変換できます。
UPDATE dept_tab SET emp_array_col = emp_array_col;
ある表内のすべての列を、UPGRADE
INCLUDING
DATA
とともにALTER
TABLE
を使用して変換できます。次に例を示します。
ALTER TYPE person_typ ADD ATTRIBUTE (photo BLOB) CASCADE NOT INCLUDING TABLE DATA; ALTER TABLE person_obj_table UPGRADE INCLUDING DATA;
ALTER
TABLE
行は、リストされた表のみを変換します。CASCADE
オプションは、他の表または依存オブジェクトが変換されないようにします。
この項では、ネストした表に含まれているオブジェクト型にネストした表属性を追加する型に複雑な変更を加える手順を説明します。
例8-6 初期スキーマ
-- Drop existing person_typ, department_type, people_typ objects or tables CREATE TYPE person_typ AS OBJECT ( idno NUMBER, name VARCHAR2(30), phone VARCHAR2(20)); / -- creating a nested table type CREATE TYPE people_typ AS TABLE OF person_typ;/ CREATE TYPE department_typ AS OBJECT ( manager person_typ, employee people_typ); // a nested table/ CREATE TABLE department OF department_typ NESTED TABLE employee STORE AS employee_store_nt;
例8-7は、新しいオブジェクトtasks_typ
およびそれを保持するネストした表の型tasks_nttab
の作成から開始されます。
属性としてネストした表tasks
をネストした表people_typ
にすでに含まれているオブジェクト型person_typ
に追加するには、例8-7および他のプログラムの両方で次の手順が必要です。
ALTER TYPE..INVALIDATE
文を発行して、型person_typ
を変更します。この文では、時間を節約するために型および表のチェックをすべて迂回して、依存オブジェクトを無効にします。表のデータには、有効化されるまでアクセスできません。
ALTER
TYPE
文には、ネストした表tasks
を追加するADD
ATTRIBUTE
が含まれます。
UPGRADE.. STORE AS
句は、影響を受けるネストした表をアップグレードし、新規の記憶表の名前を指定します。
例8-7 ネストした表属性の追加によるオブジェクト型の変更
-- Requires Ex. 8-6 CREATE TYPE tasks_typ AS OBJECT ( priority VARCHAR2(2), description VARCHAR2(30)); / CREATE TYPE tasks_nttab AS TABLE OF tasks_typ; / ALTER TYPE person_typ ADD ATTRIBUTE tasks tasks_nttab INVALIDATE; -- Propagate the change to employee_store_nt -- Specify a storage name for the new nested table ALTER TABLE employee_store_nt UPGRADE NESTED TABLE tasks STORE AS tasks_nt;
必要な場合は、person_typ
に対するCREATE OR REPLACE TYPE BODY
を使用して、対応する型本体を更新して、新しい型定義に更新します。
依存表を最新の型バージョンにアップグレードし、表データを変換します。これにより、表が検証され、データ・アクセスが再度許可されます。
ALTER TABLE department UPGRADE INCLUDING DATA;
必要に応じて、PL/SQL依存プログラム・ユニットを変更して、型に加えられた変更に対応します。
アプリケーションがC言語で書かれているか、Javaで書かれているかによって、OTTまたはJPublisherを使用して、新しいヘッダー・ファイルを生成します。
スーパータイプに新しい属性を追加すると、サブタイプの属性が新しい属性を継承するために、そのすべてのサブタイプの属性数が増大する可能性があります。継承された属性は、常に、宣言された(ローカルに定義された)属性に先行するので、新しい属性をスーパータイプに追加すると、各サブタイプのすべての宣言された属性の順序が1つずつ再帰的に増加されます。変更された型のマッピングを更新して、新しい属性を追加する必要があります。Oracle Type Translator (OTT)およびJPublisherがこれを行います。別のツールを使用する場合は、型のヘッダーが、サーバーでの型の定義と適切に同期されることを確認する必要があります。この同期が確実に行われない場合は、結果として予期しない動作が発生する可能性があります。
必要に応じてアプリケーション・コードを修正し、アプリケーションを再作成します。
ALTER TYPE
文の実行の際に、最初に、要求された型の変更について、構文上およびセマンティクス上の妥当性がチェックされます。CREATE TYPE
文についても同様の妥当性チェックおよび追加の妥当性チェックが実行されます。ターゲットの型の新しい仕様またはその依存型のいずれかについて型の妥当性が確認されない場合は、ALTER TYPE
文は異常終了します。この場合は、新しい型バージョンは作成されず、すべての依存オブジェクトが変更されないままになります。
依存表が存在する場合は、さらにチェックが行われて、表および索引に関連する制約が遵守されているかが確認されます。たとえば、削除の対象となっている属性が、パーティション化キーで使用されていないかが確認されます。ここでも、ALTER TYPE
文について、表に関連する制約のチェックが失敗すると、型の変更は異常終了し、その型の新しいバージョンは作成されません。
単一のALTER TYPE
文で複数の属性を追加する場合、指定された順序で実行されます。1つのALTER TYPE
文で複数の型の変更を指定することはできますが、属性名およびメソッド・シグネチャは1回のみの指定となります。たとえば、単一の文で同じ属性の追加と変更を行うことはできません。
次の項では、次の型の変更に関するその他の注意事項について説明します。
属性の削除
ルート型に由来するすべての属性を削除することはできません。かわりに、型を削除する必要があります。サブタイプのすべての属性はスーパータイプから継承されるため、サブタイプからすべての属性を削除しても、その属性のカウントは0 (ゼロ)にはなりません。サブタイプでローカルに宣言された属性を削除することは許可されます。
ターゲットの型でローカルに宣言された型のみを削除できます。継承された属性を、サブタイプから削除することはできません。属性がローカルに宣言された場所でその型からその属性を削除してください。
表パーティションの一部である属性または表のサブパーティション・キーの削除はできません。
オブジェクト表またはIOTの主キーOIDの属性の削除はできません。
属性が削除されると、削除された属性に対応する列は削除されます。
属性を削除すると、索引、統計、制約、および属性を参照する参照整合性制約が削除されます。
依存表のファンクション索引、クラスタ・キーまたはドメイン索引で参照される属性の長さは拡張できません。
属性の長さ、精度、スケールを縮小できません。
メソッドは、そのメソッドの定義(または再定義)が行われた型からのみ削除できます。継承されたメソッドをサブタイプから削除することはできません。また、再定義したメソッドをスーパータイプから削除することもできません。
メソッドが再定義されていない場合、CASCADE
オプションを使用してそのメソッドを削除すると、ターゲットの型に由来するメソッドおよびすべてのサブタイプが削除されます。一方、メソッドがサブタイプで再定義されている場合は、CASCADE
は実行されないで、ロールバックされます。CASCADE
が実行されるためには、メソッドを定義しているサブタイプから再定義されたメソッドを削除して、その後、スーパータイプからメソッドを削除します。
USER_DEPENDENCIES
表に、型も含めて、与えられた型に依存するすべてのスキーマ・オブジェクトがあります。また、DBMS_UTILITY.GET_DEPENDENCY
ユーティリティを実行して、型の依存関係を検索できます。
INVALIDATE
オプションを使用して、再定義されたメソッドを削除できますが、サブタイプの再定義されたバージョンは、依然として手動で削除する必要があります。サブタイプは、再定義されたバージョンを削除するように明示的に変更されないかぎり、無効な状態のままです。それまでは、妥当性チェックのためにサブタイプを再コンパイルしようとすると、「メソッドは上書きしません。」
というエラーが発生します。
CASCADE
とは異なり、INVALIDATE
は、型および表のすべてのチェックを迂回して、その型に依存するすべてのスキーマ・オブジェクトを無効とします。それらのオブジェクトは、次回のアクセス時に再検証されます。このオプションは、CASCADE
を使用するより高速に処理されますが、依存型および依存表の再検証時に問題が発生しないことが確認されている必要があります。表が無効な場合は、表データにはアクセスできません。表の妥当性が検証できない場合は、そのデータはアクセス不可のままとなります。
「型の変更の妥当性チェックに失敗した場合」を参照してください。
その型に表依存オブジェクトがない場合にかぎり、オブジェクト型をINSTANTIABLE
からNOT INSTANTIABLE
へ変更できます。
オブジェクト型のNOT INSTANTIABLE
からINSTANTIABLE
への変更は任意の時点で実行できます。このように変更した場合、表には影響しません。
ターゲットの型にサブタイプがない場合にかぎり、オブジェクト型をNOT FINAL
からFINAL
へ変更できます。
オブジェクト型をFINAL
からNOT FINAL
、またはその逆に変更する場合は、CASCADE
を使用して依存列内および依存表内のデータを即時変換する必要があります。CASCADE
オプションNOT INCLUDING TABLE DATA
を使用して、データを遅延させることはできません。
NOT FINAL
からFINAL
へは、CASCADE INCLUDING TABLE DATA
を使用する必要があります。
FINAL
からNOT FINAL
へは、CASCADE INCLUDING TABLE DATA
またはCASCADE CONVERT TO SUBSTITUTABLE
のいずれかを使用できます。
FINAL
からNOT
FINAL
に型を変更する場合、変更した型の新規サブタイプを既存の列および表に挿入するかどうかに基づいて、CASCADE
オプションを選択します。
デフォルトでは、型をFINAL
からNOT
FINAL
に変更することで、代入可能な新しい表およびその型の列を作成できますが、その型の既存の列(またはオブジェクト表)が自動的に代入可能になることはありません。実際、その逆の動作が行われます。その型の既存の列および表はNOT SUBSTITUTABLE
AT
ALL
LEVELS
とマークされます。これらの列の埋込み属性が代入可能な場合は、エラーが生成されます。変更された型の新しいサブタイプは、これらの既存の列および表には挿入できません。
既存の型の列および表を代入可能にするようオブジェクト型をNOT
FINAL
に変更する場合(NOT
SUBSTITUTABLE
とマークされていないことを前提)は、CASCADE
オプションCONVERT TO SUBSTITUTABLE
を使用します。
例8-8は、オプションCONVERT TO SUBSTITUTABLE
を含むCASCADE
の使用を示します。
例8-8 FINALからNOT FINALへの型の変換
CREATE TYPE shape AS OBJECT (
name VARCHAR2(30),
area NUMBER)
FINAL;/
ALTER TYPE shape NOT FINAL CASCADE CONVERT TO SUBSTITUTABLE;
このCASCADE
オプションにより既存の列がSUBSTITUTABLE AT ALL LEVELS
とマークされ、列に格納されたインスタンスの型ID用に新しい非表示列が追加されます。その後、変更された型のサブタイプ・インスタンスを列に格納できます。
ALTER
TYPE
文のINVALIDATE
オプションを使用して、依存オブジェクトに加えた型の変更を伝播することなく型の変更ができます。この場合、依存型および依存表の妥当性チェックは行われません。つまり、型の変更によるすべての影響が妥当であることを確認しません。かわりに、すべての依存スキーマ・オブジェクトに無効のマークが付けられます。これらのオブジェクト(型や表など)は、次回の参照時に再検証されます。型の再検証ができない場合、その型は無効のままとなり、そのような型を参照する表も、問題が修正されるまではアクセス不可となります。
表が妥当性チェックに失敗するのは、次のような理由です。型に新しい属性を追加してその表内の一部の列が、最大1000を超えた場合またはある表のパーティション化キーまたはクラスタ化キーとして使用されている属性が型から削除された場合。
型の再検証は、ALTER TYPE COMPILE
文を発行すると強制的に実行できます。無効な表の再検証を強制的に実行するには、ユーザーは、ALTER TABLE UPGRADE
文を発行して、データを最新の型バージョンに変更するかどうかを指定できます。
注意: 表の参照時にトリガーされた表の妥当性チェックにおいて、表データは常に最新の型バージョンになるよう更新されます。データの変換を延期するオプションはありません。 |
表を最新の型バージョンに変換できない場合、その表に対するINSERT
文、UPDATE
文およびDELETE
文は使用できず、その表データにはアクセスできなくなります。その表に対して次のDDLは実行できますが、無効な表を参照する他のすべての文は、その表の妥当性が検証されるまで使用できません。
DROP TABLE
TRUNCATE TABLE
ある表の%ROWTYPE
またはある列の%TYPE
、あるいはある表にある属性を使用して定義された変数を含むすべてのPL/SQLプログラムは、最新の型バージョンに基づいてコンパイルされます。その表の再検証が失敗すると、その表を参照する任意のプログラム・ユニットのコンパイルも失敗します。
表8-1に、型の属性またはメソッド定義を変更するために使用するALTER
TYPE
およびALTER
TYPE
...CASCADE
文の一部の重要なオプションを示します。
表8-1 型進化に使用するALTER TYPEオプション
オプション | 説明 |
---|---|
|
すべての依存オブジェクトを無効とします。このオプションを使用して、型および表のすべてのチェックを迂回し、時間を節約します。 このオプションは、依存型および依存表の再検証において問題が発生しないことが確実な場合に使用してください。表の妥当性が検証されるまでは表データにはアクセスできません。表の妥当性チェックができない場合は、そのデータはアクセス不可のままになります。 |
|
型の変更を依存型および依存表に伝播します。この文は、 他のオプションなしに |
|
すべてのユーザー定義列に格納されているデータを、列の型の最新バージョンに変換します。 列の型に追加された新しい属性ごとに、新しい属性がデータに追加され、 |
|
列データをそのまま維持し、型バージョンを変更しません。属性が表が参照する型から削除されても、削除された属性の対応する列は表から削除されません。ただし、その列のメタデータが未使用とマークされるのみです。削除された属性が列外(たとえば、 このオプションは、数多くの大きな表があり、1つのトランザクションでそのすべてを変換すると、ロールバック・セグメントが不足する可能性がある場合に使用します。このオプションを使用して、後で、各依存表のデータを、別個のトランザクションで変換できます( このオプションを指定すると、表のデータは、以前の型バージョンの形式のまま維持されるので、表の更新が高速化されます。ただし、この表からデータを選択するには、その列に格納されているイメージを最新の型バージョンに変換する必要があります。この操作は、後続の このオプションは、表のメタデータの更新のみを必要とするため、文を正常に実行するためにすべての表領域の読取り/書込みモードでのオンライン化が必要なわけではありません。 |
|
システムに、依存表および索引からのエラーを無視させます。エラーについては、後で問合せができるように、指定された例外表にログが作成されます。一部の表でエラーが発生した場合、依存表にアクセスできなくなる可能性があるので、このオプションは慎重に使用してください。 |
|
型を このオプションを指定せずに、型を |
関連項目: ALTER TYPE オプションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
ALTER
TABLE
を使用して、参照される型の最新バージョンに表データを変換できます。例は、「ネストした表属性の追加による型の変更」を参照してください。INCLUDING
DATA
オプションの詳細は、表8-1を参照してください。
関連項目: ALTER TABLE オプションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
この項では、属性値コンストラクタとも呼ばれるシステム定義コンストラクタおよびユーザー定義コンストラクタを使用する様々な側面を説明します。
この項の内容は次のとおりです。
属性値コンストラクタとも呼ばれるシステム定義コンストラクタの場合、型の各属性値をコンストラクタに渡す必要があります。すると、例8-9に示すように、コンストラクタにより、新しいオブジェクト・インスタンスの属性にこれらの値が設定されます。
例8-9 コンストラクタによる属性値の設定
CREATE TYPE shape AS OBJECT (
name VARCHAR2(30),
area NUMBER);
/
CREATE TABLE building_blocks of shape;
-- attribute-value constructor: Sets instance attributes to the specified values
INSERT INTO building_blocks
VALUES (
NEW shape('my_shape', 4));
NEW
は、コンストラクタへのコールの前にオプションで追加するキーワードです。このキーワードを追加することをお薦めします。
属性値コンストラクタを使用することにより、型に対して独自のコンストラクタを定義する必要がなくなります。ただし、型に宣言されたすべての属性に対して値を指定する必要があり、指定しない場合はコンストラクタ・コールのコンパイルに失敗します。
ユーザー定義コンストラクタと異なり、特に属性値コンストラクタは暗黙的でコードに表示されないため、後で型を進化させる場合、この要件によって問題が発生することがあります。型の属性を変更した場合は、その型の属性値コンストラクタも変更されます。属性を追加した場合、更新された属性値コンストラクタは、新しい属性に対する値が指定されるものとみなします。それ以外の場合は、既存のコード内の属性値コンストラクタへのコールが失敗します。
「型進化」を参照してください。
ユーザー定義コンストラクタは、属性値コンストラクタと異なり、型の各属性に対する値を明示的に設定する必要がありません。ユーザー定義コンストラクタは、任意の型の任意の数の引数を取ることができ、これらの引数は型の属性に直接マップする必要がありません。コンストラクタを定義する場合、属性を任意の適切な値に初期化できます。値が指定されない属性は、システムによってNULL
に初期化されます。
たとえば、属性を追加して型を進化させる場合、その型に対するユーザー定義コンストラクタへのコールは変更する必要がありません。型を進化させる場合、ユーザー定義コンストラクタは自動的に変更されないため、シグネチャは同じままです。ただし、新しい属性をNULL
に初期化しない場合は、コンストラクタの定義の変更が必要になることがあります。
ユーザー定義コンストラクタは、通常のメソッドと同様に型本体に定義します。ユーザー定義コンストラクタの宣言および定義は、CONSTRUCTOR FUNCTION
句を使用し、RETURN SELF AS RESULT
句で終了します。
型のコンストラクタには、型と同じ名前を使用する必要があります。例8-10では、shape
型の2つのコンストラクタ・ファンクションを定義します。例に示すとおり、異なるシグネチャを持つ複数のバージョンを定義することにより、ユーザー定義コンストラクタをオーバーロードできます。
例8-10 ユーザー定義コンストラクタの定義および実装
CREATE TYPE shape AS OBJECT ( name VARCHAR2(30), area NUMBER, CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2) RETURN SELF AS RESULT, CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2, area NUMBER) RETURN SELF AS RESULT ) NOT FINAL; / CREATE TYPE BODY shape AS CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2) RETURN SELF AS RESULT IS BEGIN SELF.name := name; SELF.area := 0; RETURN; END; CONSTRUCTOR FUNCTION shape(SELF IN OUT NOCOPY shape, name VARCHAR2, area NUMBER) RETURN SELF AS RESULT IS BEGIN SELF.name := name; SELF.area := area; RETURN; END; END; /
ユーザー定義コンストラクタには、暗黙的な第1パラメータSELF
があります。ユーザー定義コンストラクタの宣言では、このパラメータの指定はオプションです。指定する場合、このパラメータのモードはIN OUT
として宣言する必要があります。
必須句RETURN SELF AS RESULT
によって、戻されるインスタンスの最も狭い意味での型は、必ずSELF
引数の最も狭い意味での型と同じになります。コンストラクタの場合、この型は、コンストラクタが定義された型です。shape
コンストラクタへのコールに対するSELF
引数の最も狭い意味での型がshape
の場合、この句によってshape
コンストラクタからはshape
のサブタイプのインスタンスではなくshape
のインスタンスが必ず戻されます。
コンストラクタ・ファンクションがコールされると、システムはSELF
引数の属性をNULL
に初期化します。例8-10のSELF.name
など、ファンクション本体で初期化される後続の属性名は、コンストラクタ・ファンクションの引数の名前と区別するために、SELF
で修飾できます(これらの名前が同一の場合)。引数の名前が異なる場合、この修飾は不要です。
例に示すとおり、ファンクション本体には、明示的なreturn;
を含める必要があります。ただし、returnキーワードの後に、return
式を続けることはできません。システムは、新しく作成されたSELF
インスタンスを自動的に戻します。
ユーザー定義コンストラクタは、PL/SQL、CまたはJavaで実装できます。
他の型のメソッドと同様、ユーザー定義コンストラクタもオーバーロードできます。
ユーザー定義コンストラクタは継承されないため、スーパータイプで定義されたユーザー定義コンストラクタはサブタイプに隠蔽できません。ただし、ユーザー定義コンストラクタのシグネチャが属性値コンストラクタのシグネチャと完全に一致する場合、ユーザー定義コンストラクタはその型の属性値コンストラクタを隠蔽し、これを置き換えます。シグネチャが一致するには、ユーザー定義コンストラクタのパラメータ(暗黙的なSELF
パラメータの後)の名前と型が、その型の属性の名前と型と同じである必要があります。ユーザー定義コンストラクタのパラメータ(暗黙的なSELF
パラメータの後)のモードは、必ずIN
にしてください。
同じ名前とシグネチャを持つユーザー定義コンストラクタによって属性値コンストラクタが隠蔽されていない場合は、継続して属性値コンストラクタをコールできます。
たとえば、属性の追加により型が進化する場合は、型の属性値コンストラクタのシグネチャもそれに対応して変更することに注意してください。これによって、以前に隠蔽されていた属性値コンストラクタが再度使用可能になります。
他のすべてのファンクションと同様にユーザー定義コンストラクタをコールし、通常のファンクションが使用できるすべての場所で使用できます。
SELF
引数は、暗黙的に渡され、明示的に渡されません。つまり、次のように使用することはできません。
NEW constructor(instance, argument_list)
CREATE
またはALTER
TABLE
文のDEFAULT
句には、ユーザー定義コンストラクタは指定できませんが、属性値コンストラクタは指定できます。属性値コンストラクタの引数には、PL/SQLファンクションまたは他の列(疑似列LEVEL
、PRIOR
、ROWNUM
など)の参照、あるいは完全に指定されていない日付定数の参照を含めることはできません。CHECK制約式についても同様です。表の作成中または変更中に、属性値コンストラクタはCHECK制約式の一部として使用できますが、ユーザー定義コンストラクタは使用できません。
SQLでは、引数を持たないコンストラクタ・コールについても、カッコを付ける必要があります。PL/SQLでは、引数を持たないコンストラクタを起動する場合、カッコはオプションです。ただし、カッコを付けた方が、コンストラクタ・コールがファンクション・コールであることがより明確になります。次のPL/SQL例では、新しいshapeを作成するためのコンストラクタ・コールのカッコが省略されています。
shape s := NEW my_schema.shape;
NEW
キーワードおよびスキーマ名はオプションで使用してください。
例8-11では、例8-10で作成した型の下にサブタイプを作成し、ユーザー定義コンストラクタをコールする例を示します。
例8-11 ユーザー定義コンストラクタのコール
-- Requires Ex. 8-10
CREATE TYPE rectangle UNDER shape (
len NUMBER,
wth NUMBER,
CONSTRUCTOR FUNCTION rectangle(SELF IN OUT NOCOPY rectangle,
name VARCHAR2, len NUMBER, wth NUMBER) RETURN SELF as RESULT,
CONSTRUCTOR FUNCTION rectangle(SELF IN OUT NOCOPY rectangle,
name VARCHAR2, side NUMBER) RETURN SELF as RESULT);
/
SHOW ERRORS
CREATE TYPE BODY rectangle IS
CONSTRUCTOR FUNCTION rectangle(SELF IN OUT NOCOPY rectangle,
name VARCHAR2, len NUMBER, wth NUMBER) RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := len*wth;
SELF.len := len;
SELF.wth := wth;
RETURN ;
END;
CONSTRUCTOR FUNCTION rectangle(SELF IN OUT NOCOPY rectangle,
name VARCHAR2, side NUMBER) RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := side * side;
SELF.len := side;
SELF.wth := side;
RETURN ;
END;
END;
/
CREATE TABLE shape_table OF shape;
INSERT INTO shape_table VALUES(shape('shape1'));
INSERT INTO shape_table VALUES(shape('shape2', 20));
INSERT INTO shape_table VALUES(rectangle('rectangle', 2, 5));
INSERT INTO shape_table VALUES(rectangle('quadrangle', 12, 3));
INSERT INTO shape_table VALUES(rectangle('square', 12));
次の問合せでは、shape_table
内の行を選択します。
SELECT VALUE(s) FROM shape_table s;
VALUE(S)(NAME, AREA)
---------------------------------------------
SHAPE('shape1', 0)
SHAPE('shape2', 20)
RECTANGLE('rectangle', 10, 2, 5)
RECTANGLE('quadrangle', 36, 12, 3)
RECTANGLE('square', 144, 12, 12)
次のPL/SQLコードは、コンストラクタをコールします。
s shape := NEW shape('void');
SQLJオブジェクト型は、JavaクラスにマップされるSQLオブジェクト型です。SQLJオブジェクト型は属性値コンストラクタを持ちます。このオブジェクト型は、参照されたJavaクラスでコンストラクタにマップされるユーザー定義コンストラクタを持つこともできます。
例8-12 SQLJオブジェクトの作成
CREATE TYPE address AS OBJECT EXTERNAL NAME 'university.address' LANGUAGE JAVA USING SQLData( street VARCHAR2(100) EXTERNAL NAME 'street', city VARCHAR2(50) EXTERNAL NAME 'city', state VARCHAR2(50) EXTERNAL NAME 'state', zipcode NUMBER EXTERNAL NAME 'zipcode', CONSTRUCTOR FUNCTION address (SELF IN OUT NOCOPY address, street VARCHAR2, city VARCHAR2, state VARCHAR2, zipcode NUMBER) RETURN SELF AS RESULT AS LANGUAGE JAVA NAME 'university.address (java.lang.String, java.lang.String, java.lang.String, int) return address'); /
シリアル化表現のSQLJ型は、ユーザー定義コンストラクタのみ持つことができます。SQLJ型のオブジェクトの内部表現は、SQLにとって不透明であるため、SQLJ型に属性値コンストラクタは使用できません。
Oracle Databaseには、型の記述、データ・インスタンス、およびオブジェクト型やコレクション型を含むその他のSQL型のデータ・インスタンスの集合の動的なカプセル化およびアクセスを可能にする3つの特殊なSQLデータ型があります。この3つの型は、匿名のコレクション型を含めた匿名型の作成にも使用できます。
この3つのSQL型は、不透明型として実装されます。つまり、これらの型の内部構造は、データベースには認識されません。不透明型のデータへの問合せは、目的に合ったファンクション(通常は3GLルーチン)を実装することによってのみ実行されます。Oracle Databaseは、そのようなファンクションを実装するためにOCIとPL/SQL APIの両方を提供しています。
一時型の構造は、データベースにとって不透明です。そのため、それらは永続的に格納することはできません。一時型の列は作成できず、永続型の属性にできません。
表8-2で、この3つの汎用SQL型を説明します。
表8-2 汎用SQL型
型 | 説明 |
---|---|
型記述型。
|
|
自己記述的データ・インスタンスの型。 次のものは
|
|
自己記述的なデータ集合の型。 次のものは
|
この3つの型はそれぞれ、データベースに対してネイティブな組込み型や、名前の有無にかかわらずオブジェクト型およびコレクション型と併用できます。型は、型記述、単独インスタンスおよび他の型のインスタンス・セットを動的に操作するための汎用的な方法を提供します。APIを使用すると、あらゆる種類の型について一時的なANYTYPE
記述を作成できます。同様に、任意のSQL型のデータ値を作成するかANYDATA
に変換(キャスト)し、ANYDATA
をSQL型に変換できます。さらに、値セットとANYDATASET
の場合も同様です。
汎用型は、ストアド・プロシージャを使用した作業を簡単にします。汎用型を使用して、標準型の記述およびデータをカプセル化し、カプセル化された情報を汎用型のパラメータに渡せます。プロシージャ本体では、カプセル化されたデータおよび任意の型の型記述の処理方法を詳細に記述できます。
また、基礎となる様々な型のカプセル化されたデータを、型ANYDATA
またはANYDATASET
の単一の表の列に格納することもできます。たとえば、ANYDATA
をアドバンスト・キューイングと併用して、異質な型のデータのキューイングをモデル化できます。基礎となるデータ型のデータは、他の任意のデータ同様に、問合せを実行できます。
例8-13では、SYS.ANYDATA
に組み込まれたメソッドを使用して、SYS.ANYDATA
表列に格納されているデータの情報にアクセスするPL/SQLプロシージャを定義して実行します。
例8-13 SYS.ANYDATAの使用
CREATE OR REPLACE TYPE dogowner AS OBJECT ( ownerno NUMBER, ownername VARCHAR2(10) ); / CREATE OR REPLACE TYPE dog AS OBJECT ( breed VARCHAR2(10), dogname VARCHAR2(10) ); / CREATE TABLE mytab ( id NUMBER, data SYS.ANYDATA ); INSERT INTO mytab VALUES ( 1, SYS.ANYDATA.ConvertNumber (5) ); INSERT INTO mytab VALUES ( 2, SYS.ANYDATA.ConvertObject ( dogowner ( 5555, 'John') ) ); commit; CREATE OR REPLACE procedure P IS CURSOR cur IS SELECT id, data FROM mytab; v_id mytab.id%TYPE; v_data mytab.data%TYPE; v_type SYS.ANYTYPE; v_typecode PLS_INTEGER; v_typename VARCHAR2(60); v_dummy PLS_INTEGER; v_n NUMBER; v_dogowner dogowner; non_null_anytype_for_NUMBER exception; unknown_typename exception; BEGIN OPEN cur; LOOP FETCH cur INTO v_id, v_data; EXIT WHEN cur%NOTFOUND; v_typecode := v_data.GetType ( v_type /* OUT */ ); CASE v_typecode WHEN Dbms_Types.Typecode_NUMBER THEN IF v_type IS NOT NULL THEN RAISE non_null_anytype_for_NUMBER; END IF; v_dummy := v_data.GetNUMBER ( v_n /* OUT */ ); Dbms_Output.Put_Line ( To_Char(v_id) || ': NUMBER = ' || To_Char(v_n) ); WHEN Dbms_Types.Typecode_Object THEN v_typename := v_data.GetTypeName(); IF v_typename NOT IN ( 'HR.DOGOWNER' ) THEN RAISE unknown_typename; END IF; v_dummy := v_data.GetObject ( v_dogowner /* OUT */ ); Dbms_Output.Put_Line ( To_Char(v_id) || ': user-defined type = ' || v_typename || '(' || v_dogowner.ownerno || ', ' || v_dogowner.ownername || ' )' ); END CASE; END LOOP; CLOSE cur; EXCEPTION WHEN non_null_anytype_for_NUMBER THEN RAISE_Application_Error ( -20000, 'Paradox: the return AnyType instance FROM GetType ' || 'should be NULL for all but user-defined types' ); WHEN unknown_typename THEN RAISE_Application_Error ( -20000, 'Unknown user-defined type ' || v_typename || ' - program written to handle only HR.DOGOWNER' ); END; / SELECT t.data.gettypename() FROM mytab t; SET SERVEROUTPUT ON; EXEC P;
前述にコード例の問合せおよびプロシージャPにより、次のような出力が生成されます。
T.DATA.GETTYPENAME()
-------------------------------------------------------------
SYS.NUMBER
HR.DOGOWNER
1: NUMBER = 5
2: user-defined type = HR.DOGOWNER(5555, John )
前述の3つの汎用SQL型に対応するのが、それらをモデル化するOCI型です。各OCI型は、それぞれの型の作成およびアクセスに使用する関数のセットを備えています。
OCIType
: SYS.ANYTYPE
に対応しています。
OCIAnyData
: SYS.ANYDATA
に対応しています。
OCIAnyDataSet
: SYS.ANYDATASET
に対応しています。
関連項目:
|
Oracle Databaseは、レコード集合に対する操作に使用する、MAX
、MIN
およびSUM
をはじめとする数多くの定義済集計ファンクションを提供しています。これらの定義済集計ファンクションは、スカラー・データに対してのみ使用できます。ただし、これらのファンクションのカスタム実装を独自に作成することもできれば、複雑なデータ(たとえば、オブジェクト型、不透明型、LOB型を使用して格納されているマルチメディア・データなど)に対して使用する新しい集計ファンクションを定義することもできます。
ユーザー定義集計ファンクションは、Oracleデータベースの組込み集計ファンクションと同様に、SQL DML文で使用されます。このようなファンクションがサーバーに登録されていると、ネイティブのルーチンではなく、ユーザーが定義した集計ルーチンがコールされます。
ユーザー定義集計ファンクションは、スカラー・データに対しても使用できます。たとえば、財務アプリケーションまたは科学アプリケーションに対応付けられた複雑な統計データを処理するために特殊な集計ファンクションを実装すると効果的な場合があります。
ユーザー定義集計ファンクションは、拡張フレームワークの機能です。それらの実装には、ODCIAggregate
インタフェース・ルーチンを使用します。
関連項目: ODCIAggregate インタフェース・ルーチンを使用して、ユーザー定義集計ファンクションを実装する方法については、『Oracle Databaseデータ・カートリッジ開発者ガイド』を参照してください。 |
ネストした表のロケータを使用して、データの取得時にパフォーマンスを向上できます。
コレクション型は、C++やJavaなどの言語でのシステム固有の型または構造へ直接マップすることはありません。これらの言語を使用しているアプリケーションは、OCIなどのOracleデータベース・インタフェースを介して、コレクションの内容にアクセスする必要があります。
一般に、クライアントが(オブジェクトをフェッチすることによって)ネストした表に明示的または暗黙的にアクセスすると、コレクション値全体がクライアント・プロセスに戻されます。パフォーマンス上の理由から、クライアントは、コレクションの内容全体を取り出すのを遅延または回避する場合があります。Oracleデータベースでは、ネストした表の実際の値ではなくロケータを使用することによって、これに対処します。実際にコレクションの内容にアクセスが行われたときは、その内容がクライアントに自動的に転送されます。
ネストした表のロケータは、コレクション値へのハンドルに似ています。検索実行時のデータベース・スナップショットを確保することで、ネストした表の値またはコピー・セマンティクスを保とうとします。スナップショットによって、コレクション要素がロケータを使用してフェッチされたときに、データベースがネストした表の値の正しいインスタンスを取り出せるようになります。ロケータの有効範囲は1つのセッションにかぎられ、複数のセッションにまたがって使用することはできません。データベース・スナップショットが使用されているため、ネストした表の更新率が高い場合は、「スナップショットが古すぎます
」というエラーが発生する場合があります。LOBロケータとは異なり、ネストした表のロケータは純粋なロケータであり、コレクション・インスタンスを変更するためには使用できません。