Oracle PL/SQL オブジェクト型のチュートリアルと例

PL/SQLのオブジェクト型とは何ですか?

オブジェクト指向プログラミングは、再利用可能なコンポーネントや複雑なアプリケーションの構築に特に適しています。これらは「アクション」ではなく「オブジェクト」を中心に構成されます。つまり、プログラムは単一のアクションではなくオブジェクト全体で動作し、対話するように設計されています。この概念により、プログラマーはオブジェクト エンティティ レベルで詳細を設定および操作できます。

以下の図は、銀行口座がオブジェクト エンティティとみなされるオブジェクト タイプの例を示しています。 オブジェクト属性には、銀行口座など、いくつかの属性値を保持するものが含まれます。 これは口座番号、銀行残高などであり、オブジェクト メソッドは金利の計算、銀行取引明細書の生成など、特定のプロセスを完了する必要があるものを記述します。

PL/SQLのオブジェクト型

PL/SQL では、オブジェクト指向プログラミングはオブジェクト型に基づいています。

オブジェクト タイプは、現実世界のあらゆるエンティティを表すことができます。 この章では、さらに多くのオブジェクト タイプについて説明します。

オブジェクトタイプのコンポーネント

PL / SQLの object type には主に XNUMX つのコンポーネントが含まれています。

  1. Attributes
  2. メンバー/メソッド

Attributes

属性は、データが格納される列またはフィールドです。 各属性は、その属性の処理および保存タイプを定義するデータタイプにマップされます。 属性には有効な属性を指定できます。 PL/SQLデータ型、または別のオブジェクト タイプである可能性があります。

メンバー/メソッド

メンバーまたはメソッドは、オブジェクト タイプで定義されるサブプログラムです。 データの保存には使用されません。 これらは主に、オブジェクト タイプ内のプロセスを定義するために使用されます。 たとえば、オブジェクト タイプを設定する前にデータを検証します。 これらはオブジェクト タイプ セクションで宣言され、オブジェクト タイプのオブジェクト タイプ本体セクションで定義されます。 オブジェクトタイプのボディセクションはオプションの部分です。 メンバーが存在しない場合、オブジェクト型には本体部分が含まれません。

オブジェクトを作成する Oracle

オブジェクト型はサブプログラム レベルでは作成できません。オブジェクト タイプはスキーマ レベルでのみ作成できます。 オブジェクト型がスキーマで定義されると、同じものをサブプログラムで使用できます。 オブジェクトタイプは「CREATE TYPE」を使用して作成できます。 型本体は、そのオブジェクト型を作成した後にのみ作成できます。

オブジェクトを作成する Oracleオブジェクトを作成する Oracle

CREATE TYPE<object_type_name> AS OBJECT
(
<attribute_l><datatype>,
.
.
);
/
CREATE TYPE BODY<object_type_name> AS OBJECT
(
MEMBER[PROCEDURE|FUNCTION]<member_name> 
IS
<declarative section>
BEGIN
<execution part>
END;‭
.
.	‬
);
/

構文の説明:

  • 上記の構文は、属性を使用した 'OBJECT' とメソッドを使用した 'OBJECT-BODY' の作成を示しています。
  • メソッドはオブジェクト本体でオーバーロードすることもできます。

オブジェクト型の宣言初期化

PL/SQL の他のコンポーネントと同様に、オブジェクト型もプログラムで使用する前に宣言する必要があります。

オブジェクト タイプが作成されると、それをサブプログラムの宣言セクションで使用して、そのオブジェクト タイプの変数を宣言できます。

サブプログラム内で変数がオブジェクト型として宣言されると、実行時にそのオブジェクト型の新しいインスタンスが作成され、この新しく作成されたインスタンスは変数名を参照できます。 この方法により、単一のオブジェクト タイプで複数の値を異なるインスタンスに保存できます。

オブジェクト型の宣言初期化

DECLARE
<variable_name> <object_type_name>;
BEGIN
.
.
END;
/

構文の説明:

  • 上記の構文は、宣言セクションでのオブジェクト型としての変数の宣言を示しています。

変数がサブプログラム内でオブジェクト型として宣言されると、その変数はアトミックに null になります。つまり、オブジェクト全体が null になります。プログラム内で変数を使用するには、値で初期化する必要があります。変数はコンストラクターを使用して初期化できます。

コンストラクターは、オブジェクト型と同じ名前で参照できるオブジェクトの暗黙的なメソッドです。 以下の構文は、オブジェクト タイプの初期化を示しています。

オブジェクト型の宣言初期化

DECLARE
<variable_name> <object_type_name>; 
BEGIN
<variable_name>:=<object_type_name>();
END;
/

構文の説明:

  • 上記の構文は、null 値を使用したオブジェクト型インスタンスの初期化を示しています。
  • オブジェクト自体は初期化されているため null ではありませんが、オブジェクト内の属性は値を割り当てていないため null になります。

コンストラクター

コンストラクターは、オブジェクト型と同じ名前で参照できるオブジェクトの暗黙的なメソッドです。 オブジェクトが初めて参照されるときは常に、このコンストラクターが暗黙的に呼び出されます。

これらのコンストラクターを使用してオブジェクトを初期化することもできます。 コンストラクターは、オブジェクト型の本体にオブジェクト型と同じ名前のメンバーを定義することで明示的に定義できます。

: 次の例では、オブジェクト タイプ メンバーを使用して、値 ('RRR'、1005、20000、1000) および ('PPP'、1006、20000、1001) を持つレコードを emp テーブルに挿入します。データが挿入されたら、オブジェクト タイプ メンバーを使用して同じデータを表示します。また、明示的なコンストラクターを使用して、1001 番目のレコードのマネージャー ID にデフォルトで XNUMX の値を設定します。

以下の手順で実行していきます。

  • Step1:
  • オブジェクトタイプの作成
  • オブジェクトタイプ本体
  • ステップ 2: emp_no 1005 の暗黙的なコンストラクターを介して、作成されたオブジェクト型を呼び出すための匿名ブロックを作成します。
  • ステップ 3: emp_no 1006 の明示的なコンストラクターを通じて、作成されたオブジェクト型を呼び出すための匿名ブロックを作成します。

ステップ1) オブジェクト型とオブジェクト型本体の作成

コンストラクター

CREATE TYPE emp_object AS OBJECT(
emp_no NUMBER,
emp_name VARCHAR2(50),
salary NUMBER,
manager NUMBER,
CONSTRUCTOR FUNCTION emp_object(p_emp_no NUMBER, p_emp_name VARCHAR2,
p_salary NUMBER) RETURN SELF AS RESULT),
MEMBER PROCEDURE insert_records,
MEMBER PROCEDURE display_records);
/

コンストラクター

CREATE OR REPLACE TYPE BODY emp_object AS
CONSTRUCTOR FUNCTION emp_object(p_emp_no NUMBER,p_emp_name VARCHAR2,
p_salary NUMBER)
RETURN SELF AS RESULT
IS
BEGIN
Dbms_output.put_line(’Constructor fired..');
SELF.emp_no:=p_emp_no;|
SELF.emp_name:=p_emp_name;
SELF.salary:=p_salary;
SELF.managerial:=1001;
RETURN;
END:
MEMBER PROCEDURE insert_records
IS
BEGIN
INSERT INTO emp VALUES(emp_noemp_name,salary,manager);
END
MEMBER PROCEDURE display_records
IS
BEGIN
Dbms_output.put_line('Employee Name:'||emp_name);
Dbms_output.put_line('Employee Number:'||emp_no);
Dbms_output.put_line('Salary':'||salary);
Dbms_output.put_line('Manager:'||manager);
END:
END:
/

コードの説明

  • コード行 1 ~ 9: 4 つの属性と 3 つのメンバーを持つ「emp_object」オブジェクト タイプを作成します。 これには、パラメーターが 3 つだけあるコンストラクターの定義が含まれています。 (実際の暗黙的なコンストラクターには、オブジェクト型に存在する属性の数と同じ数のパラメーターが含まれます)
  • コード行 10: タイプボディを作成します。
  • コード行 11 ~ 21: 明示的なコンストラクターを定義します。 パラメータ値を属性に割り当て、属性「manager」の値をデフォルト値「1001」で割り当てます。
  • コード行 22 ~ 26: 属性値が「emp」テーブルに挿入されるメンバー「insert_records」を定義します。
  • コード行 27 ~ 34: オブジェクトタイプ属性の値を表示するメンバー「display_records」を定義します。

出力

タイプが作成されました

型本体が作成されました

ステップ2) emp_no 1005 の暗黙的なコンストラクターを介して作成されたオブジェクト型を呼び出すための匿名ブロックの作成

コンストラクター

DECLARE
guru_emp_det emp_object;
BEGIN
guru_emp_det:=emp_object(1005,’RRR',20000,1000);
guru_emp_det.display_records;
guru_emp_det.insert_records;
COMMIT;
END;

コードの説明

  • コード行 37 ~ 45: 暗黙的なコンストラクターを使用してレコードを挿入します。 コンストラクターの呼び出しには、実際の属性値の数が含まれます。
  • コード行 38: guru_emp_det を 'emp_object' のオブジェクト タイプとして宣言します。
  • コード行 41: ステートメント 'guru_emp_det.display_records' は 'diplay_records' メンバー関数を呼び出し、属性値が表示されます
  • コード行 42: ステートメント「guru_emp_det.insert_records」は「insert_records」メンバー関数を呼び出し、属性値がテーブルに挿入されます。

出力

従業員名: RRR

社員番号: 1005

給与:20000

マネージャー : 1000

ステップ3) emp_no 1006 の明示的なコンストラクターを通じて作成されたオブジェクト型を呼び出すための匿名ブロックの作成

コンストラクター

DECLARE
guru_emp_det emp_object;
BEGIN
guru_emp_det:=emp_object(1006,'PPP',20000);
guru_emp_det.display_records;
guru_emp_det.insert_records;
COMMIT;
END;
/

出力

Employee Name:PPP 
Employee Number:1006 
Salary:20000 
Manager:1001

コードの説明:

  • コード行 46 ~ 53: 明示的なコンストラクターを使用してレコードを挿入します。
  • コード行 46: guru_emp_det を 'emp_object' のオブジェクト タイプとして宣言します。
  • コード行 50: ステートメント 'guru_emp_det.display_records' は 'display_records' メンバー関数を呼び出し、属性値が表示されます
  • コード行 51: ステートメント「guru_emp_det.insert_records」は「insert_records」メンバー関数を呼び出し、属性値がテーブルに挿入されます。

オブジェクト型の継承

継承プロパティを使用すると、サブオブジェクト タイプがスーパー オブジェクト タイプまたは親オブジェクト タイプのすべての属性およびメンバーにアクセスできるようになります。

サブオブジェクト タイプは継承オブジェクト タイプと呼ばれ、スーパー オブジェクト タイプは親オブジェクト タイプと呼ばれます。 以下の構文は、親および継承されたオブジェクト タイプを作成する方法を示しています。

オブジェクト型の継承

CREATE TYPE <object_type_name_parent> AS OBJECT
(
<attribute_l><datatype>,
.
.
)NOT FINAL;
/

構文の説明:

  • 上記の構文は、SUPER タイプの作成を示しています。

オブジェクト型の継承

CREATE TYPE<object_type_name_sub>UNDER<object_type_name_parent>
(
<attribute_l><datatype>,
.
);
/

構文の説明:

  • 上記の構文は SUB タイプの作成を示しています。 これには、親オブジェクト タイプのすべてのメンバーと属性が含まれます。

Example1: 以下の例では、継承プロパティを使用して、次のレコード ('RRR'、1002、1007) にマネージャー ID が '20000' のレコードを挿入します。

上記のプログラムを次の手順で実行します。

  • Step1:SUPERタイプを作成します。
  • Step2: SUBタイプとボディを作成します。
  • ステップ 3: SUB タイプを呼び出すための匿名ブロックを作成します。

ステップ1) SUPER タイプまたは親タイプを作成します。

オブジェクト型の継承

CREATE TYPE emp_object AS OBJECT(
emp_no NUMBER,
emp_name VARCHAR2(50),
salary NUMBER,
manager NUMBER,
CONSTRUCTOR FUNCTION emp_object(p_emp_no NUMBER,p_emp_name VARCHAR2(50),
p_salary NUMBER)RETURN SELF AS RESULT),
MEMBER PROCEDURE insert_records,
MEMBER PROCEDURE display_records)NOT FINAL;
/

コードの説明:

  • コード行 1 ~ 9: 4 つの属性と 3 つのメンバーを持つ「emp_object」オブジェクト タイプを作成します。 これには、パラメーターが 3 つだけあるコンストラクターの定義が含まれています。 「NOT FINAL」として宣言されているため、親タイプになります。

ステップ2) SUPERタイプの下にSUBタイプを作成します。

オブジェクト型の継承

CREATE OR REPLACE TYPE sub_emp_object 
UNDER emp_object
(default_manager NUMBER,MEMBER PROCEDURE insert_default_mgr);
/


CREATE OR REPLACE TYPE BODY sub_emp_object 
AS
MEMBER PROCEDURE insert_default_mgr 
IS
BEGIN
INSERT INTO emp
VALUES(emp_no,emp_name:salary,manager):
END;
END;
/

コードの説明:

  • コード行 10 ~ 13: 追加の XNUMX つの属性 'default_manager' とメンバー プロシージャ宣言を備えた継承型として sub_emp_object を作成します。
  • コード行 14: 継承されたオブジェクト タイプの本体を作成しています。
  • コード行 16-21: マネージャー値を除く、'SUPER' オブジェクト タイプの値を使用してレコードを "emp" テーブルに挿入するメンバー プロシージャを定義します。 マネージャーの値には、「SUB」タイプの「default_manager」を使用しています。

ステップ3) SUB 型を呼び出すための匿名ブロックの作成

オブジェクト型の継承

DECLARE
guru_emp_det sub_emp_object;
BEGIN
guru_emp_det:= sub_emp_object(1007,'RRR',20000,1000,1002);
guru_emp_det.insert_default_mgr;
COMMIT;
END;
/

コードの説明:

  • コード行 25: 'guru_emp_det' を 'sub_emp_object' タイプとして宣言しています。
  • コード行 27: 暗黙的なコンストラクターを使用してオブジェクトを初期化します。 コンストラクターには 5 つのパラメーター (PARENT タイプの 4 つの属性と SUB タイプの 2 つの属性) があります。 最後のパラメータ (1002) は、default_manager 属性の値を定義します。
  • コード行 28: メンバー「insert_default_mgr」を呼び出して、コンストラクターで渡されたデフォルトのマネージャー ID を持つレコードを挿入します。

PL/SQLオブジェクトの同等性

同じオブジェクトに属するオブジェクト インスタンスは、等しいかどうか比較できます。 このためには、オブジェクトタイプに「ORDER」メソッドと呼ばれる特別なメソッドが必要です。

この 'ORDER' メソッドは数値型を返す関数である必要があります。 入力として XNUMX つのパラメーターを取ります (最初のパラメーター: 自己オブジェクト インスタンスの ID、XNUMX 番目のパラメーター: 別のオブジェクト インスタンスの ID)。

XNUMX つのオブジェクト インスタンスの ID が比較され、結果が数値で返されます。

  • 正の値は、SELF オブジェクト インスタンスが別のインスタンスよりも大きいことを表します。
  • 負の値は、SELF オブジェクト インスタンスが別のインスタンスより小さいことを表します。
  • ゼロは、SELF オブジェクト インスタンスが別のインスタンスと等しいことを表します。
  • いずれかのインスタンスが null の場合、この関数は null を返します。

PL/SQLオブジェクトの同等性

CREATE TYPE BODY<object_type_name_ 1>AS OBJECT
(
  ORDER MEMBER FUNCTION match(<parameter> object_type_name_ 1)
  RETURN INTEGER IS		
  BEGIN
    IF <attribute_name>parameter <attribute_name>THEN
      RETURN -1; --any negative number will do
    ELSIF id>c.id THEN
      RETURN 1; —any positive number will do
    ELSE
      RETURN 0;
    END IF;
  END;
  .
  .
);
/

構文の説明:

  • 上記の構文は、等価性チェックのために型本体に含める必要がある ORDER 関数を示しています。
  • この関数のパラメータは、同じオブジェクト タイプのインスタンスである必要があります。
  • 上記の関数は「obj_instance_1.match(obj_instance_2)」として呼び出すことができ、この式は次のような数値を返します。ここで、obj_instance_1 と obj_instance_2 は object_type_name のインスタンスです。

例1: 次の例では、2 つのオブジェクトを比較する方法を説明します。2 つのインスタンスを作成し、それらの間で属性 'salary' を比較します。2 つの手順を実行します。

  • ステップ 1: オブジェクトのタイプと本体を作成します。
  • ステップ 2: オブジェクト インスタンスの比較を呼び出すための匿名ブロックを作成します。

ステップ1) オブジェクトのタイプと本体を作成します。

PL/SQLオブジェクトの同等性

PL/SQLオブジェクトの同等性

CREATE TYPE emp_object_equality AS OBJECT(
salary NUMBER,
ORDER MEMBER FUNCTION equals(c emp_object_equality)RETURN INTEGER);
/
CREATE TYPE BODY emp_object_equality AS
ORDER MEMBER FUNCTION equals(c emp_object_equality)RETURN INTEGER 
IS
BEGIN‭	‬
IF salary<c.salary
THEN RETURN -1;
ELSIF salary>c.salary
THEN RETURN 1;
ELSE
RETURN 0;
END IF:‭	‬
END;
END;
/

コードの説明:

  • コード行 1 ~ 4: 1 つの属性と 1 つのメンバーを持つ「emp_object_equality」オブジェクト タイプを作成します。
  • コード行 6 ~ 16: SELF インスタンスの 'salary' 属性とパラメータ インスタンス タイプを比較する ORDER 関数を定義します。SELF の給与の方が少ない場合は負の値を返し、SELF の給与の方が大きい場合は正の値を返します。給与が等しい場合は 0 を返します。

コード出力:

タイプが作成されました

ステップ2) オブジェクト インスタンスの比較を呼び出すための匿名ブロックを作成します。

PL/SQLオブジェクトの同等性

DECLARE
l_obj_l emp_object_equality;
l_obj_2 emp_object_equality;
BEGIN
l_obj_l:=emp_object_equality(15000); 
l_obj_2:=emp_object_equality(17000);
IF l_obj_1.equalS(l_obj_2)>0
THEN
Dbms_output.put_line(’Salary of first instance is greater’):
ELSIF l_obj_l.equalS(l_obj_2)<0
THEN
Dbms_output.put_line(’Salary of second instance is greater’); 
ELSE
Dbms_output.put_line(’Salaries are equal’);
END IF;
END;
/

出力

Salary of second instance is greater

コードの説明:

  • コード行 20: emp_object_equality 型の l_obj_1 を宣言します。
  • コード行 21: emp_object_equality 型の l_obj_2 を宣言します。
  • コード行 23: l_obj_1 を給与値「15000」で初期化しています
  • コード行 24: l_obj_1 を給与値「17000」で初期化しています
  • コード行 25 ~ 33: ORDER 関数からの戻り値に基づいてメッセージを出力します。

まとめ

この章では、オブジェクトのタイプとそのプロパティについて見てきました。 PL/SQL オブジェクトのコンストラクター、メンバー、属性、継承、等価性についても説明しました。