4 PL/SQLによるデータ・カートリッジの実装

PL/SQLを使用して、データ・カートリッジのメソッドを実装できます。メソッドとは、データ・カートリッジを使用して定義されたデータについて、許可される操作を定義するプロシージャおよびファンクションです。

4.1 メソッド

メソッドとは、オブジェクト型定義の一部で、その型の属性を操作できるプロシージャまたはファンクションのことです。この種のメソッドはメンバー・メソッドとも呼ばれ、オブジェクト型の構成要素として指定するときにキーワードMEMBERを取ります。

メソッドの実装、メソッドのコールおよびメソッドでの属性の参照を示す単純な例を考えます。

関連項目:

4.1.1 メソッドの実装

メソッドを実装するには、PL/SQLコードを作成し、それをCREATE TYPE BODY文で指定します。オブジェクト型にメソッドがない場合、そのオブジェクト型に対するCREATE TYPE BODY文は不要です。

例4-1に、rational_typeオブジェクト型の定義を示します。

例4-2の定義は、CREATE TYPE BODY文のnormalizeメソッドの定義に使用するファンクションgcdを定義しています。

例4-3の文では、オブジェクト型rational_typeのメソッド(rat_to_realnormalizeおよびplus)を実装します。

4.1.1.1 オブジェクト型の定義

例4-1 オブジェクト型の定義

CREATE TYPE rational_type AS OBJECT
( numerator INTEGER,
  denominator INTEGER,
  MAP MEMBER FUNCTION rat_to_real RETURN REAL,
  MEMBER PROCEDURE normalize,
  MEMBER FUNCTION plus (x rational_type)
       RETURN rational_type);
4.1.1.2 「Greatest Common Divisor(最大公約数)」ファンクションの定義

例4-2 「Greatest Common Divisor(最大公約数)」ファンクションの定義

CREATE FUNCTION gcd (x INTEGER, y INTEGER) RETURN INTEGER AS
-- Find greatest common divisor of x and y. For example, if
-- (8,12) is input, the greatest common divisor is 4.
-- This normalizes (simplifies) fractions.
-- (You need not try to understand how this code works, unless
--  you are a math wizard. It does.)
--
   ans INTEGER;
BEGIN
   IF (y <= x) AND (x MOD y = 0) THEN
      ans := y;
   ELSIF x < y THEN 
      ans := gcd(y, x);  -- Recursive call
   ELSE
      ans := gcd(y, x MOD y);  -- Recursive call
   END IF;
   RETURN ans;
END;
4.1.1.3 オブジェクト型のメソッドの実装

例4-3 オブジェクト型のメソッドの実装

CREATE TYPE BODY rational_type
( MAP MEMBER FUNCTION rat_to_real RETURN REAL IS
   -- The rat-to-real function converts a rational number to 
   -- a real number. For example, 6/8 = 0.75
   BEGIN
      RETURN numerator/denominator;
   END;

   -- The normalize procedure simplifies a fraction.
   -- For example, 6/8 = 3/4
   MEMBER PROCEDURE normalize IS
      divisor INTEGER := gcd(numerator, denominator);
   BEGIN
      numerator := numerator/divisor;
      denominator := denominator/divisor;
   END;

   -- The plus function adds a specified value to the
   -- current value and returns a normalized result.
   -- For example, 1/2 + 3/4 = 5/4
   -- 
   MEMBER FUNCTION plus(x rational_type)
            RETURN rational_type IS
            -- Return sum of SELF + x
   BEGIN
      r = rational_type(numerator*x.demonimator +
             x.numerator*denominator,
             denominator*x.denominator);
                 -- Example adding 1/2 to 3/4:
                 -- (3*2 + 1*4) / (4*2)
      -- Now normalize (simplify). Here, 10/8 = 5/4
      r.normalize;
      RETURN r;
   END;
END;

4.1.2 メソッドのコール

メソッドをコールするには、例4-4の構文を使用します。

SQL文でのみ例4-5の構文を使用できます。

例4-6に、PL/SQLでのメソッドget_emp_salのコール方法を示します。

メソッドをコールするには、SELF組込みパラメータを使用する方法もあります。各メソッドの暗黙的な第1パラメータはメソッドのコール対象となるオブジェクトの名前であるため、例4-7では、例4-6salary := employee.get_emp_sal();の行と同じアクションが実行されます。

例4-7では、employeeget_emp_sal()メソッドのコール対象となるオブジェクトの名前です。

4.1.2.1 メソッドをコールするための一般的な構文

例4-4 メソッドのコール(一般構文)

object_name.method_name([parameter_list])
4.1.2.2 メソッドをコールするためのSQL構文

例4-5 メソッドのコール(SQL構文)

correlation_variable.method_name([parameter_list])
4.1.2.3 メソッドをコールするためのPL/SQL構文

例4-6 メソッドのコール(PL/SQL構文)

DECLARE
   employee employee_type;
   salary number;
   ...
BEGIN
   salary := employee.get_emp_sal();
   ...
END;
4.1.2.4 SELF組込みパラメータの使用

例4-7 SELF組込みパラメータの使用

salary := get_emp_sal(SELF => employee);

4.1.3 メソッドでの属性の参照

メンバー・メソッドは修飾子を使用せずに同じオブジェクト型の属性およびメンバー・メソッドを参照できるため、メソッドのコール対象となるオブジェクトには、常に組込み参照SELFが提供されます。

2つの文で変数var1の値が42に設定される例4-8を考えてみます。

var1 := 42およびSELF.var1 := 42には同じ効果があります。var1はオブジェクト型a_typeの属性の名前で、set_var1はこのオブジェクト型のメンバー・メソッドであるため、メソッド・コードでは修飾なしでvar1にアクセスできます。ただし、コードの読みやすさとメンテナンス性を考慮して、このコンテキストにキーワードSELFを使用するとvar1を明確に参照できます。

4.1.3.1 変数値の設定

例4-8 変数値の設定

CREATE TYPE a_type AS OBJECT (
   var1 INTEGER,
   MEMBER PROCEDURE set_var1);
CREATE TYPE BODY a_type (
   MEMBER PROCEDURE set_var1 IS
   BEGIN
      var1 := 42;
      SELF.var1 := 42;
   END set_var1;
);

4.2 PL/SQLコードのデバッグ

PL/SQLコードをデバッグする場合に最も単純な方法の1つは、SQL*Plusでメソッド、ブロックまたは文を対話形式で個別にテストし、問題があれば修正してから次の文に進むことです。エラー・メッセージの詳細が必要な場合は、SHOW ERRORS文を入力します。実行時デバッグ用に文を表示することも検討してください。 例4-9に示されているように、コードにPUTおよびPUTLINE文を挿入し、変数と式の値を端末に出力することにより、ストアド・プロシージャおよびパッケージのデバッグには、DBMS_OUTPUTパッケージを使用できます。

PL/SQLトレース・ツールは、アプリケーション・コードの例外条件に関する詳細情報を提供します。このツールを使用すると、サーバー側PL/SQL文の実行をトレースできます。オブジェクト型のメソッドを直接トレースすることはできませんが、メソッドでコールするPL/SQLファンクションまたはプロシージャをトレースできます。また、このトレース・ツールでは、アプリケーション・コードの例外条件に関する情報も提供されます。トレース出力は、Oracleサーバーのトレース・ファイルに書き込まれます。ファイルにアクセスできるのは、データベース管理者のみです。

関連項目:

例4-9 デバッグを目的とした端末へ変数値の出力

Location in module: location
Parameter name: name
Parameter value: value

4.2.1 データ・カートリッジのCおよびC++開発者のための注意事項

CまたはC++プログラマにとっては、複数のPL/SQL表記規則と要件に違いがあります。

  • =は代入ではなく等号を意味します。

  • :=はAlgolではなく代入を意味します。

  • VARRAYは索引0ではなく索引1から始まります。

  • コメントは//または/*ではなく二重ハイフン(--)で始まります。

  • IF文にはTHENキーワードが必要です。

  • IF文はEND IFキーワードで終了する必要があります(ELSE句がある場合はその後に挿入します)。

  • PRINTF文はありません。この文に相当する機能はDBMS_OUTPUT.PUT_LINE文です。この文では、リテラルと変数のテキストを二重縦線(||)で区切ります。

  • ファンクションには戻り値が必要で、プロシージャには戻り値を使用できません。

  • ファンクションをコールする場合は、代入演算子の右辺に置く必要があります。

  • PL/SQLキーワードの多くは、変数名として使用できません。

4.2.2 共通の潜在的エラー

データ・カートリッジの作成中は、いくつかの種類のエラーが発生する可能性があります。

4.2.2.1 シグネチャの不一致
13/19    PLS-00538: subprogram or cursor '<name>' is declared in an object
         type specification and must be defined in the object type body
15/19    PLS-00539: subprogram '<name>' is declared in an object type body
         and must be defined in the object type specification

前述のメッセージの一方または両方が表示される場合は、プロシージャまたはファンクションのシグネチャに誤りがあります。つまり、オブジェクト仕様部に入力したファンクションまたはプロシージャのプロトタイプと、オブジェクト本体内の定義に不一致があります。

パラメータの順序、スペル(大/小文字の区別を含む)およびファンクションの戻り値が同一であることを確認してください。入力エラーを防ぐには、コピーおよびペーストを使用します。

4.2.2.2 RPCのタイムアウト
ORA-28576: lost RPC connection to external procedure agent
ORA-06512: at "<name>", line <number>
ORA-06512: at "<name>", line <number>
ORA-06512: at line 34

このエラーは、DLLのデバッガを終了した後に発生する場合があります。デバッガの外でプログラムを再起動してください。

4.2.2.3 パッケージの破損
ERROR at line 1:
ORA-04068: existing state of packages has been discarded
ORA-04063: package body "<name>" has errors
ORA-06508: PL/SQL: could not find program unit being called
ORA-06512: at "<name>", line <number>
ORA-06512: at line <number>

このエラーは、既存のデータ・カートリッジを拡張する際に発生することがあります。これは、パッケージが破損しており、再コンパイルする必要があることを示します。

再コンパイルを実行する前に、対象となるパッケージに依存する表およびオブジェクト型をすべて削除する必要があります。Windows NTシステム上で依存性を検索するには、Oracle Administratorツールバーを使用します。「スキーマ」ボタンをクリックし、sys\change_on_installとしてログインし、作成したパッケージと表を検索します。SQL*Plusインタフェースで、例4-10のようにSQL文を入力して、これらのパッケージと表を削除します。

例4-10 パッケージおよび表の削除

Drop type type_name;
Drop table table_name cascade constraints;

この後、例4-11のSQL文を使用して、再コンパイルを実行できます。

例4-11 パッケージの再コンパイル

Alter type type_name compile body;
Alter type type_name compile specification;