4 PL/SQLによるデータ・カートリッジの実装
PL/SQLを使用して、データ・カートリッジのメソッドを実装できます。メソッドとは、データ・カートリッジを使用して定義されたデータについて、許可される操作を定義するプロシージャおよびファンクションです。
4.1 メソッド
メソッドとは、オブジェクト型定義の一部で、その型の属性を操作できるプロシージャまたはファンクションのことです。この種のメソッドはメンバー・メソッドとも呼ばれ、オブジェクト型の構成要素として指定するときにキーワードMEMBER
を取ります。
メソッドの実装、メソッドのコールおよびメソッドでの属性の参照を示す単純な例を考えます。
関連項目:
-
メソッドの指定、名前および過負荷状態の詳細は、「Oracle Database概要」を参照してください。
-
詳細および例は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
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_real
、normalize
および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-6のsalary := employee.get_emp_sal();
の行と同じアクションが実行されます。
例4-7では、employee
はget_emp_sal()
メソッドのコール対象となるオブジェクトの名前です。
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.3 メソッドでの属性の参照
メンバー・メソッドは修飾子を使用せずに同じオブジェクト型の属性およびメンバー・メソッドを参照できるため、メソッドのコール対象となるオブジェクトには、常に組込み参照SELF
が提供されます。
2つの文で変数var1
の値が42
に設定される例4-8を考えてみます。
文var1 := 42
およびSELF.var1 := 42
には同じ効果があります。var1
はオブジェクト型a_type
の属性の名前で、set_var1
はこのオブジェクト型のメンバー・メソッドであるため、メソッド・コードでは修飾なしでvar1
にアクセスできます。ただし、コードの読みやすさとメンテナンス性を考慮して、このコンテキストにキーワードSELF
を使用すると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サーバーのトレース・ファイルに書き込まれます。ファイルにアクセスできるのは、データベース管理者のみです。
関連項目:
-
トレースのツールについては、『Oracle Database SQLチューニング・ガイド』を参照してください。
-
DBMS_OUTPUT
パッケージについては、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』および『Oracle Database PL/SQL言語リファレンス』を参照してください。
例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\<password>
としてログインして、作成したパッケージと表を検索します。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;