3.2 PL/SQLでのオブジェクトの操作

この項では、PL/SQLでオブジェクトの属性とメソッドを操作する方法について説明します。

この項には次のトピックが含まれます:

3.2.1 ドット表記法によるオブジェクト属性へのアクセス

属性は名前で参照します。属性にアクセスしたり属性値を変更する際には、ドット表記法を使用します。

属性名を連鎖させれば、ネストされたオブジェクト型の属性にアクセスできます。例3-3では、ドット表記を使用して例3-2と同じ出力を生成します。

例3-3 オブジェクトの属性へのアクセス

-- Requires Ex. 3-1
DECLARE
  emp employee_typ;
BEGIN
  emp := employee_typ(315, 'Francis', 'Logan', 'FLOGAN',
        '415.555.0100', '01-MAY-04', 'SA_MAN', 11000, .15, 101, 110, 
         address_typ('376 Mission', 'San Francisco', 'CA', '94222'));
  DBMS_OUTPUT.PUT_LINE(emp.first_name || ' '  || emp.last_name);
  DBMS_OUTPUT.PUT_LINE(emp.address.street);
  DBMS_OUTPUT.PUT_LINE(emp.address.city || ', '  ||emp. address.state || ' ' ||
                       emp.address.postal_code);   
END;
/

3.2.2 オブジェクトのコンストラクタとメソッドに対するコール

コンストラクタは、ファンクション・コールが使用できるところであればどこからでもコールできます。

例3-3および例3-4に示すように、コンストラクタはすべてのファンクションと同様、式の一部としてコールされます。

コンストラクタにパラメータを渡してコールした場合は、インスタンス化するオブジェクトの属性に初期値が代入されます。デフォルト・コンストラクタをコールしてすべての属性値を入れる場合、すべての属性についてパラメータを指定する必要があります。定数や変数とは異なり、属性はデフォルト値を持つことができません。コンストラクタのコールには、位置表記法のかわりに名前表記法を使用することもできます。

例3-4 オブジェクト表への行の挿入

-- Requires Ex. 3-1
DECLARE
  emp employee_typ;
BEGIN
  INSERT INTO employee_tab VALUES (employee_typ(310, 'Evers', 'Boston', 'EBOSTON',
   '617.555.0100', '01-AUG-04', 'SA_REP', 9000, .15, 101, 110, 
    address_typ('123 Main', 'San Francisco', 'CA', '94111')) );
  INSERT INTO employee_tab VALUES (employee_typ(320, 'Martha', 'Dunn', 'MDUNN',
    '650.555.0150', '30-SEP-04', 'AC_MGR', 12500, 0, 101, 110,
    address_typ('123 Broadway', 'Redwood City', 'CA', '94065')) );
END;
/
SELECT VALUE(e) from employee_tab e;

3.2.3 オブジェクト・メソッドへのアクセス

メソッドは、パッケージ・サブプログラムと同様、ドット表記法を使用してコールします。

例3-5では、オブジェクトの属性を表示するためにdisplay_addressメソッドをコールしています。オブジェクトの値を返すVALUEファンクションの使用方法に注目してください。VALUEは、相関変数を引数にとります。ここでいう相関変数とは、オブジェクト表内の行に関連付けられた行変数または表別名です。

例3-5 オブジェクト・メソッドへのアクセス

-- Requires Ex. 3-1 and Ex. 3-4
DECLARE
  emp employee_typ;
BEGIN
  SELECT VALUE(e) INTO emp FROM employee_tab e WHERE e.employee_id = 310;
  emp.display_address();
END;
/

SQL文では、パラメータのないメソッドをコールするには空のパラメータ・リストが必要です。プロシージャ文では、コールを連鎖しないかぎり空のパラメータ・リストはオプションとなり、連鎖する場合は、最後のコールを除くすべてのコールにパラメータ・リストが必要です。また、2つのファンクション・コールを連鎖する場合は、1つ目のファンクションが2つ目のファンクションに渡すためのオブジェクトを戻す必要があります。

DML操作中にADTコンストラクタのかわりにPL/SQLファンクションが使用される場合は、ファンクションがDML実行の一部として複数回実行されることがあります。ファンクションを出現ごとに1回のみ実行するには、決定的ファンクションにする必要があります。

静的メソッドをコールする場合は、型のインスタンスを指定するのではなく、表記法type_name.method_nameを使用します。

サブタイプのインスタンスを使用してメソッドをコールする場合、型階層内のどのメソッドが実際に実行されるかは、宣言の内容によって異なります。サブタイプがスーパータイプから継承したメソッドをオーバーライドしている場合は、サブタイプの実装が使用されます。それ以外の場合は、スーパータイプの実装が使用されます。この機能を動的メソッド・ディスパッチといいます。

3.2.4 オブジェクトの更新および削除

PL/SQLブロック内から、オブジェクト表の行を変更または削除できます。

例3-6 オブジェクト表の行の更新および削除

-- Requires Ex. 3-1 and 3-4
DECLARE
  emp employee_typ;
BEGIN
  INSERT INTO employee_tab VALUES (employee_typ(370, 'Robert', 'Myers', 'RMYERS',
   '415.555.0150', '07-NOV-04', 'SA_REP', 8800, .12, 101, 110, 
    address_typ('540 Fillmore', 'San Francisco', 'CA', '94011')) );
  UPDATE employee_tab e SET e.address.street = '1040 California' 
     WHERE e.employee_id = 370;
  DELETE FROM employee_tab e WHERE e.employee_id = 310;
END;
/
SELECT VALUE(e) from employee_tab e;

3.2.5 REF修飾子によるオブジェクトの操作

REFの取得には、相関変数または別名を引数にとるREFファンクションを使用できます。

REFは、変数、パラメータ、フィールドまたは属性として宣言できます。REFはSQLデータ操作文の入力変数または出力変数として使用できます。

例3-7 REF修飾子を使用したオブジェクト表内の行の更新

-- Requires Ex. 3-1, 3-4, and 3-6
DECLARE
  emp         employee_typ;
  emp_ref REF employee_typ;
BEGIN
  SELECT REF(e) INTO emp_ref FROM employee_tab e WHERE e.employee_id = 370;
  UPDATE employee_tab e 
    SET e.address = address_typ('8701 College', 'Oakland', 'CA', '94321')
    WHERE REF(e) = emp_ref;
END;
/

PL/SQLでは、REFを使用してナビゲートすることはできません。たとえば、例3-8のようなREFを使用した代入は実行できません。かわりに、DEREFファンクションを使用するか、UTL_REFパッケージをコールしてオブジェクトにアクセスしてください。

例3-8 SELECT INTO文でのDEREFの使用(間違った試行)

-- Requires Ex. 3-1, 3-4, and 3-6
DECLARE 
  emp           employee_typ;
  emp_ref   REF employee_typ;
  emp_name      VARCHAR2(50);
BEGIN
  SELECT REF(e) INTO emp_ref FROM employee_tab e WHERE e.employee_id = 370;
  -- the following assignment raises an error, not allowed in PL/SQL  emp := DEREF(emp_ref);  --  cannot use DEREF in procedural statements
  emp_name := emp.first_name || ' ' || emp.last_name;
  DBMS_OUTPUT.PUT_LINE(emp_name);
END;
/

この代入により、後述のようなエラーが発生します。

not allowed in PL/SQL
-- emp_name := emp_ref.first_name || ' ' || emp_ref.last_name;
-- emp := DEREF(emp_ref); not allowed, cannot use DEREF in procedural statements

関連項目: