2.4 オブジェクトに便利なファンクションおよび演算子

いくつかのファンクションや演算子は、オブジェクトやオブジェクトへの参照を扱う際に特に役に立ちます。

使用例は、このマニュアルの他の章でも示しています。

注意:

PL/SQLの場合、VALUEREFおよびDEREFファンクションが現れるのは、SQL文の中のみです。SQLファンクションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

内容は次のとおりです。

2.4.1 CAST

CASTは、ある組込みデータ型またはコレクション型の値を、別の組込みデータ型またはコレクション型の値に変換します。次に例を示します。

例2-33 CASTファンクションの使用

CREATE TYPE person_list_typ AS TABLE OF person_typ;/

SELECT CAST(COLLECT(contact) AS person_list_typ) 
  FROM contacts;

関連項目:

SQL CASTファンクションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

2.4.2 CURSOR

CURSOR式は、ネストしたカーソルを戻します。

CURSOR形式の式は、PL/SQLのREF CURSORと同等で、REF CURSOR引数としてファンクションに渡すことが可能です。

関連項目:

SQL CURSOR式の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

2.4.3 DEREF

SQL文のDEREFファンクションは、REFに対応するオブジェクト・インスタンスを戻します。

DEREFにより戻されるオブジェクト・インスタンスは、REFの宣言された型か、またはこの型のサブタイプになる可能性があります。

次に示す文は、表contact_refからperson_typオブジェクトを戻します。

例2-34 DEREFファンクションの使用

-- Using the DEREF Function example, not sample schema
SELECT DEREF(c.contact_ref), c.contact_date 
  FROM contacts_ref c;

関連項目:

2.4.4 IS OF type

IS OF typeの述語は、オブジェクト・インスタンスの型の特化レベルを検証します。

たとえば、次の問合せでは、person_obj_table表に格納されている学生インスタンス(学生のすべてのサブタイプなど)がすべて取り出されます。

例2-35 IS OF type演算子を使用したサブタイプ値の問合せ

-- Using the IS OF type Operator to query Value of a subtype 
SELECT VALUE(p) 
  FROM person_obj_table p
WHERE VALUE(p) IS OF (student_typ);

指定されたサブタイプではないオブジェクト、または指定されたサブタイプのサブタイプに対しては、IS OFよりFALSEが戻されます。指定されたサブタイプのサブタイプは、指定されたサブタイプのさらに特化されたバージョンにすぎません。このようなサブタイプを除外するには、ONLYキーワードが使用できます。このキーワードを使用すると、IS OFは指定された型を除くすべての型に対してFALSEを戻します。

次に示す文は、個人、従業員および学生が入っているオブジェクト表person_obj_tableのオブジェクトを検証し、指定された2つの個人サブタイプであるemployee_typおよびstudent_typ(そのサブタイプが存在する場合は、これらのサブタイプも含まれます)のオブジェクトのみに対するREFを戻します。

-- Using the IS OF type Operator to query for multiple subtypes
SELECT REF(p) 
  FROM person_obj_table p
WHERE VALUE(p) IS OF (employee_typ, student_typ);

次に、PL/SQLの同様の例を示します。個人が従業員または学生の場合、コードによって操作が実行されます。

-- Using the IS OF type Operator with PL/SQL 
DECLARE 
  var person_typ; 
BEGIN 
  var := employee_typ(55, 'Jane Smith', '1-650-555-0144', 100, 'Jennifer Nelson');
  IF var IS OF (employee_typ, student_typ) THEN 
     DBMS_OUTPUT.PUT_LINE('Var is an employee_typ or student_typ object.');
  ELSE
     DBMS_OUTPUT.PUT_LINE('Var is not an employee_typ or student_typ object.');
  END IF;
END;
/

次の文は、最も狭い意味での型または特化された型がstudent_typである学生のみを戻します。表またはビューにstudent_typのサブタイプ(part_time_student_typなど)のオブジェクトが含まれている場合、これらのオブジェクトは除外されます。この例は、TREATファンクションを使用して、学生オブジェクトをビューの宣言された型person_typからstudent_typに変換します。

-- Using the IS OF type Operator to query for specific subtype only
SELECT TREAT(VALUE(p) AS student_typ)
  FROM person_obj_table p 
WHERE VALUE(p) IS OF(ONLY student_typ);

REFが示すオブジェクトの型を検証する場合、IS OF typeの述語を使用して検証する前に、REFの参照を解除するには、DEREFファンクションが使用できます。

たとえば、contact_refREF person_typとして宣言すると、次に示すように学生についての行のみが取得できます。

-- Using the IS OF type Operator with DEREF 
SELECT * 
  FROM contacts_ref
WHERE DEREF(contact_ref) IS OF (student_typ);

関連項目:

SQL IS OF type条件の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

2.4.5 REF

SQL文のREFファンクションは、オブジェクト表またはビューの相関名(または表別名)を引数としてとり、その表またはビューからオブジェクト・インスタンスの参照(REF)を戻します。

REFファンクションにより、表またはビューの宣言された型のオブジェクトの参照、またはその型のサブタイプのオブジェクトの参照が戻せます。たとえば、次の文は、idno属性が12である学生や従業員の参照など個人全員の参照を戻します。

例2-36 REFファンクションの使用

-- Using the REF Function example, not sample schema
SELECT REF(p) 
  FROM person_obj_table p
  WHERE p.idno = 12;

関連項目:

SQL REFファンクションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

2.4.6 SYS_TYPEID

SYS_TYPEIDファンクションを問合せで使用すると、引数として渡されたオブジェクト・インスタンスの最も狭い意味での型の型ID (非表示の型)が戻されます。

オブジェクト・インスタンスの最も狭い意味での型とは、インスタンスが属する型(つまり、ルート型から最も離れたインスタンスから取り出される型)です。たとえば、Timが定時制の学生だとすると、彼は学生であると同時に個人ですが、彼の最も狭い意味での型は定時制の学生です。

このファンクションは、代入可能なすべての列と対応付けられた非表示の型判別式の列から型IDを戻します。FINALのルート型についてはNULLの型IDを戻します。

この関数の構文は次のとおりです。

SYS_TYPEID(object_type_value)

SYS_TYPEIDファンクションを使用するには、オブジェクト型の引数を付ける必要があります。非表示の型判別式の列について索引が作成できるようにすることが、このファンクションの主な目的です。

型階層に属するすべての型に、型階層内で一意な非NULL型IDが割り当てられます。型階層に属さない型には、NULL型IDが与えられます。

FINALのルート型を除くすべての型が、型階層に属します。FINALのルート型には、継承により関連付けられる型はありません。

  • これはFINALの型のため、そこから導出されるサブタイプを持つことはできません。

  • ルート型自身が他の型から導出されることはないため、ルート型のスーパータイプは存在しません。

SYS_TYPEIDの例として、person_typの代入可能なオブジェクト表person_obj_tableを検討してみましょう。person_typは、サブタイプとしてstudent_typを持ち、student_typのサブタイプとしてpart_time_student_typを持つ階層のルート型です。例2-20を参照してください。

次の問合せでは、SYS_TYPEIDを使用します。このファンクションは、person_obj_table表の中にあるオブジェクト・インスタンスのname属性およびtypeidを取得します。インスタンスのそれぞれが、異なる型を持ちます。

例2-37 SYS_TYPEIDファンクションの使用

-- Using the SYS_TYPEID Function example, not sample schema
SELECT name, SYS_TYPEID(VALUE(p)) typeid FROM person_obj_table p;

関連項目:

2.4.7 TABLE()

テーブル・ファンクションとは、物理データベース表のように問い合せたり、PL/SQLのコレクション変数に割り当てることが可能な、行、ネストした表またはVARRAYのコレクションを生成するファンクションです。

テーブル・ファンクションは、問合せのFROM句でデータベース表の名前のように使用したり、問合せのSELECTリストで列名のように使用できます。

テーブル・ファンクションは、行のコレクションを入力として取ることができます。入力コレクション・パラメータには、VARRAYやPL/SQL表のようなコレクション型か、またはREF CURSORを使用できます。

Oracle Databaseによりテーブル・ファンクションの結果が繰り返し戻されるようにするには、PIPELINEDを使用します。テーブル・ファンクションにより、ネストした表またはVARRAY型が戻されます。問合せのFROM句のファンクション名の前にTABLEキーワードを使用して、テーブル・ファンクションを問い合せます。

関連項目:

TABLE()ファンクションの詳細は、次を参照してください

2.4.8 TREAT

TREATファンクションは、階層内の指定された異なる型(通常は、式の宣言された型のサブタイプ)として、特定の式を操作できるかを、実行時にチェックします。

つまり、TREATファンクションは、スーパータイプのインスタンスをサブタイプのインスタンスとして扱おうとします(たとえば、個人を学生として扱います)。その人が学生であれば、学生が持つ可能性のある別の属性やメソッドと一緒に、学生として戻されます。その人が学生でない場合、TREATはSQLでNULLを戻します。

TREATは、主に次の2つの目的で使用します。

  • ナローイング代入で、階層内のさらに特化された型の変数に式が代入できるように、式のタイプを変更するため(スーパータイプの値をサブタイプに設定するため)。

  • 行または列の宣言された型のサブタイプの属性またはメソッドにアクセスするため。

    Tの代入可能なオブジェクト表または列には、Tのすべてのサブタイプのすべての属性についての非表示列があります。これらの非表示列にはサブタイプの属性データが含まれますが、DESCRIBE文でこれらの非表示列をリストすることはできません。TREATを使用すると、これらの列にアクセスできます。

2.4.8.1 ナローイング代入でのTREATの使用

ナローイング代入(スーパータイプの値をサブタイプに設定する代入)では、TREATファンクションを使用します。ワイドニング代入との違いは、「型をまたがる代入」を参照してください。

例2-38では、TREATにより、すべてのstudent_typインスタンス(のみ)が、person_typ型(student_typのスーパータイプ)のperson_obj_tableから戻されます。この文は、TREATを使用して、pの型をperson_typからstudent_typに変更します。

例2-38 問合せで特定のサブタイプを戻すためのTREATファンクションの使用

-- Using the TREAT Function to Return a Specific Subtype in a Query example,
-- not sample schema
SELECT TREAT(VALUE(p) AS student_typ)
  FROM person_obj_table p;

それぞれのpについてTREATによる変更が成功するのは、pの値の最も狭い意味での型または特化された型がstudent_typか、そのサブタイプの1つである場合のみです。pが学生でない個人の場合、またはpNULLの場合、TREATはSQLではNULLを戻し、PL/SQLでは例外を発行します。

REF式の宣言された型を変更する場合にも、TREATが使用できます。次に例を示します。

-- Using the TREAT Function to modify declared type of a REF example,
-- not sample schema
SELECT TREAT(REF(p) AS REF student_typ)
  FROM person_obj_table p;

この例は、すべてのstudent_typインスタンスに対してREFを戻します。学生ではない個人インスタンスについては、SQLの場合はNULL REFが戻され、PL/SQLの場合は例外が発行されます。

2.4.8.2 サブタイプの属性またはメソッドにアクセスするためのTREATファンクションの使用

行または列の宣言された型のサブタイプの属性またはメソッドにアクセスするために使用するのが、おそらくTREATの最も重要な使用方法です。次の問合せでは、major属性を持つ個人、学生および定時制の学生全員のこの属性が取り出されます。学生ではない人については、NULLが戻されます。

例2-39 特定のサブタイプの属性にアクセスするためのTREATファンクションの使用

SELECT name, TREAT(VALUE(p) AS student_typ).major major 
  FROM person_obj_table p;

majorstudent_typの属性であっても、表personsの宣言された型であるperson_typではないため、次の問合せは意図したとおりには機能しません。

SELECT name, VALUE(p).major major FROM person_obj_table p -- incorrect;

次に、PL/SQLの例を示します。

DECLARE 
  var person_typ; 
BEGIN 
  var := employee_typ(55, 'Jane Smith', '1-650-555-0144', 100, 'Jennifer Nelson');
  DBMS_OUTPUT.PUT_LINE(TREAT(var AS employee_typ).mgr);
END;
/

関連項目:

SQL TREATファンクションの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

2.4.9 VALUE

SQL文では、VALUEファンクションはオブジェクト表またはオブジェクト・ビューの相関変数(表の別名)を引数としてとり、表またはビューの行に対応するオブジェクト・インスタンスを戻します。

VALUEファンクションにより、行の宣言された型のインスタンスか、またはその型のサブタイプを戻すことができます。

例2-40では、最初にpart_time_student_typを作成し、次に学生や従業員を含む個人全員がperson_typの表person_obj_tableから戻されるSELECT問合せを示しています。

例2-40 VALUEファンクションの使用

-- Requires Ex. 2-31 and 2-32
CREATE TYPE part_time_student_typ UNDER student_typ (
  number_hours NUMBER);
/
SELECT VALUE(p) FROM person_obj_table p;

定時制の学生のみ、つまり最も狭い意味での型がpart_time_student_typであるインスタンスを取り出すには、ONLYキーワードを使用して選択範囲を限定します。

SELECT VALUE(p) FROM person_obj_table p 
  WHERE VALUE(p) IS OF (ONLY part_time_student_typ);

次の例では、オブジェクト表内のオブジェクト・インスタンスを更新するためにVALUEが使用されています。

UPDATE person_obj_table p
   SET VALUE(p) = person_typ(12, 'Bob Jones', '1-650-555-0130')
   WHERE p.idno = 12;

関連項目: