この項では、PL/SQLによって提供される次のような機能および利点を説明します。
PL/SQLの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
PL/SQLを使用すれば、カーソルを定義して操作するために、DECLARE、OPEN、FETCHおよびCLOSE文を使用する必要はありません。かわりに、カーソルFORループを使用でき、ループ索引をレコードとして暗黙的に宣言し、指定された問合せに関連付けられているカーソルをオープンして、データを繰り返しカーソルからフェッチしてレコードに入れてから、カーソルをクローズします。次に例を示します。
DECLARE ... BEGIN FOR emprec IN (SELECT empno, sal, comm FROM emp) LOOP IF emprec.comm / emprec.sal > 0.25 THEN ... ... END LOOP; END;
ドット表記法を使用すると、レコード内のコンポーネントを参照できます。
PL/SQLにはプロシージャとファンクションと呼ばれる2種類のサブプログラムがあり、これらを使用すると、各動作を分離できるため、アプリケーションの開発が容易になります。一般に、プロシージャはアクションを実行するために使用し、ファンクションは値を計算するために使用します。
プロシージャおよびファンクションには拡張性があります。つまり、プロシージャとファンクションを使用することにより、PL/SQL言語を必要に応じて調整できます。たとえば、新しい部門を作成するプロシージャが必要な場合、次のように記述します。
PROCEDURE create_dept (new_dname IN CHAR(14), new_loc IN CHAR(13), new_deptno OUT NUMBER(2)) IS BEGIN SELECT deptno_seq.NEXTVAL INTO new_deptno FROM dual; INSERT INTO dept VALUES (new_deptno, new_dname, new_loc); END create_dept;
このプロシージャをコールすると、プロシージャでは新しい部門名と場所を受け取り、部門番号データベース順序の次の値を選択し、その新しい番号、名前および場所をdept表に挿入してから、新しい番号をコール元に戻します。
仮パラメータの動作を定義するには、パラメータ・モードを使用します。パラメータ・モードにはIN (デフォルト)、OUTおよびIN OUTの3つがあります。INパラメータを使用すると、コールされるサブプログラムに値を渡せます。OUTパラメータを使用すると、サブプログラムのコール元に値を戻せます。IN OUTパラメータを使用すると、コールされるサブプログラムに初期値を渡し、更新された値をコール元に戻すことができます。
それぞれの実パラメータのデータ型は、対応する仮パラメータのデータ型に変換可能であることが必要です。表7-1は、データ型間の正当な変換を示しています。
PL/SQLでは、論理的に関連する型、プログラム・オブジェクトおよびサブプログラムを1つのパッケージにまとめることができます。プロシージャ・データベース拡張機能がある場合、パッケージをコンパイルして、Oracleデータベースに格納でき、そのデータベースの内容は多くのアプリケーションで共有できます。
パッケージには通常、仕様部および本体の2つの部分があります。仕様部とは、アプリケーションへのインタフェースで、使用可能な型、定数、変数、例外、カーソルおよびサブプログラムが宣言されます。本体は、カーソルとサブプログラムを定義し、仕様を実行します。次の例では、2つの雇用プロシージャをパッケージ化しています。
PACKAGE emp_actions IS -- package specification PROCEDURE hire_employee (empno NUMBER, ename CHAR, ...); PROCEDURE fire_employee (emp_id NUMBER); END emp_actions; PACKAGE BODY emp_actions IS -- package body PROCEDURE hire_employee (empno NUMBER, ename CHAR, ...) IS BEGIN INSERT INTO emp VALUES (empno, ename, ...); END hire_employee; PROCEDURE fire_employee (emp_id NUMBER) IS BEGIN DELETE FROM emp WHERE empno = emp_id; END fire_employee; END emp_actions;
パッケージ仕様部内の宣言のみ参照可能で、アプリケーションからアクセスできます。パッケージ本体中の詳細な実装内容は非表示のためアクセスできません。
PL/SQLにはTABLEの名前の複合データ型が用意されています。TABLE型のオブジェクトは、PL/SQL表と呼ばれ、データベース表をモデルとしています(まったく同じではありません)。PL/SQL表は1列からなり、主キーを使用して、配列と同じ方法で行にアクセスします。列は、任意のスカラー型(CHAR、DATEまたはNUMBERなど)にできますが、主キーはBINARY_INTEGER型、PLS_INTEGER型またはVARCHAR2型にする必要があります。
ブロック、プロシージャ、ファンクションまたはパッケージのいずれかの宣言部でPL/SQL表型を宣言できます。次の例では、NumTabTypと呼ばれるTABLE型を宣言しています。
... DECLARE TYPE NumTabTyp IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; ... BEGIN ... END; ...
次の例に示すように、一度NumTabTyp型を定義すると、その型のPL/SQL表を宣言できます。
num_tab NumTabTyp;
識別子num_tabは、PL/SQL表全体を表しています。
配列に似た構文を使用してPL/SQL表の中の行を参照し、主キーの値を指定します。たとえば、num_tabの名前のPL/SQL表の中の9番目の行を参照するには次のように指定します。
num_tab(9) ...
%ROWTYPE属性を使用して、表の中の行を表すレコード、またはカーソルによってフェッチされる行を表すレコードを宣言できます。しかし、レコード内のコンポーネントのデータ型は指定できません。また、ユーザー独自のコンポーネントも定義できません。複合データ型RECORDを使用すると、これらの制限事項を取り除くことができます。
RECORD型のオブジェクトはレコードと呼ばれます。PL/SQL表とは異なり、レコードには一意の名前を持つコンポーネントがあります。コンポーネントのデータ型はそれぞれ異なっていてもかまいません。たとえば、ある従業員について異なる種類のデータ(名前、給与、雇用日など)があるとします。このデータは、型は異なりますが、論理的に関連しています。従業員の名前、給与および雇用日などのコンポーネントを持つレコードによって、1つの論理単位としてデータを処理できます。
ブロック、プロシージャ、ファンクションまたはパッケージのいずれかの宣言部で、レコード型およびレコード・オブジェクトを宣言できます。次の例では、DeptRecTypと呼ばれるRECORD型を宣言しています。
DECLARE TYPE DeptRecTyp IS RECORD (deptno NUMBER(4) NOT NULL, -- default is NULL allowed dname CHAR(9), loc CHAR(14));
コンポーネント宣言は変数宣言に似ているため注意してください。各コンポーネントには一意の名前および固有のデータ型を指定します。コンポーネント宣言にNOT NULLオプションを追加すると、そのコンポーネントにはNULLを割り当てられません。
次の例に示すように、一度DeptRecTypを定義すると、その型のレコードを宣言できます。
dept_rec DeptRecTyp;
識別子dept_recは、レコード全体を表しています。
ドット表記法を使用すると、レコード内の個別コンポーネントを参照できます。たとえば、次のようにdept_recレコード内でdnameコンポーネントを参照します。
dept_rec.dname ...