プライマリ・コンテンツに移動
Pro*C/C++プログラマーズ・ガイド
12c リリース1(12.1)
B71397-03
目次へ移動
目次
索引へ移動
索引

前
次

PL/SQLの利点

この項では、PL/SQLによって提供される次のような機能および利点を説明します。

PL/SQLの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

パフォーマンスの向上

PL/SQLによって、オーバーヘッドの削減、パフォーマンスの改善および生産性の向上が図れます。たとえば、PL/SQLを使用しないと、Oracleは一度に1つずつSQL文を処理する必要があります。その結果、各SQL文によってサーバーへの別のコールが発生し、オーバーヘッドが増加します。しかし、PL/SQLを使用すると、SQL文のブロック全体をサーバーに送信できます。これにより、アプリケーションとOracleとの間の通信は最小限になります。

Oracleとの統合

PL/SQLは、Oracleサーバーと密接に統合されています。たとえば、PL/SQLデータ型の大部分は、Oracleデータ・ディクショナリにとっても固有のデータ型です。さらに、次の例に示すとおり、データ・ディクショナリ内に格納された列定義に基づいて変数を宣言するための%TYPE属性を指定できます。

job_title  emp.job%TYPE; 

したがって、列の厳密なデータ型を知る必要はありません。しかも、列定義を変更すると、変数宣言もそれに応じて自動的に変更されます。これによって、データ独立性を提供し、メンテナンス・コストを削減し、データベース変更時にプログラムが順応できるようになります。

カーソルFORループ

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表

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 ...