ヘッダーをスキップ
Oracle Database PL/SQL言語リファレンス
11g リリース1(11.1)
E05670-03
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

1 PL/SQLの概要

PL/SQLは、SQLの手続き型拡張機能としてオラクル社が提供する言語であり、完全な移植性を備えた高性能のトランザクション処理言語です。 この章では、そのメリットと、主な特徴およびアーキテクチャについて説明します。

ここでのトピック:

PL/SQLのメリット

PL/SQLのメリットは、次のとおりです。

SQLとの緊密な統合

SQLは、柔軟かつ強力で、しかも覚えやすいという特長のために、標準データベース言語になりました。 SELECTINSERTUPDATEDELETEなどの、いくつかの英語に似た文を使用して、リレーショナル・データベースに格納されているデータを簡単に操作できます。

PL/SQLとSQLは緊密に統合されています。 PL/SQLでは、SQLのデータ操作、カーソル制御およびトランザクション制御のすべての文、SQLのすべてのファンクション、演算子および擬似列を使用できます。

PL/SQLでは、SQLデータ型を完全にサポートしています。 PL/SQLとSQLのデータ型間で変換を行う必要はありません。 たとえば、PL/SQLプログラムがSQL型VARCHAR2のデータベース列から値を取得する場合は、その値をVARCHAR2型のPL/SQL変数に格納できます。 PL/SQL言語の特別な機能によって、データ型を指定せずに表の列や行を操作できるため、表の定義が変更された場合のメンテナンス作業が簡略化されます。

PL/SQLにおけるSQL問合せの実行および結果セットの処理は、一般的なスクリプト言語でテキスト・ファイルを開いて各行を処理する場合と同様に簡単です。 データベース・オブジェクトのメタデータへのアクセスおよびデータベースのエラー条件の処理にPL/SQLを使用して、データベース管理用のユーティリティ・プログラムを作成できます。このプログラムは信頼性が高く、各操作が正常に終了したかどうかの出力を読みやすい形式で生成します。 PL/SQLは、トリガーやオブジェクト型など、データベースの多くの機能で使用されます。 トリガー本体およびオブジェクト型のメソッドをPL/SQLで作成できます。

PL/SQLは静的SQLおよび動的SQLの両方をサポートしています。 静的SQLとは、コンパイル時にテキスト全体がわかるSQLのことです。 動的SQLとは、実行時までテキスト全体が不明なSQLのことです。 動的SQLを使用すると、アプリケーションをより柔軟で多目的に使用できます。 PL/SQLでの静的SQLの使用方法の詳細は、第6章「静的SQLの使用」を参照してください。 動的SQLの使用方法の詳細は、第7章「動的SQLの使用」を参照してください。

高いパフォーマンス

PL/SQLがあれば、複数文のブロック全体をデータベースに一度に送信できます。 そのため、データベースとアプリケーションの間のネットワークの通信量を大幅に削減できます。 図1-1に示すように、PL/SQLブロックおよびサブプログラム(プロシージャとファンクション)を使用してSQL文をグループ化してから、データベースに送信して実行することができます。 PL/SQL言語には、ループの中で発行されたSQL文をさらにスピードアップする機能も備わっています。

PL/SQLストアド・サブプログラムは一度コンパイルされてから実行可能なフォームで格納されるため、サブプログラム・コールは効果的です。 ストアド・サブプログラムはデータベース・サーバー内で実行されるため、ネットワーク上で一度コールすると大規模なジョブを開始できます。 この作業の分割によってネットワークの通信量が軽減され、応答時間が改善されます。 ストアド・サブプログラムはキャッシュされ、ユーザー間で共有されます。これによって、必要なメモリー量とコール・オーバーヘッドが減少します。

図1-1 PL/SQLによるパフォーマンスの向上

PL/SQLによるパフォーマンスの向上
「図1-1 PL/SQLによるパフォーマンスの向上」の説明

高い生産性

PL/SQLでは、データを操作するコードを非常にコンパクトにすることができます。 Perlのようなスクリプト言語が、ファイルからデータを読み込み、変換して、書き込むのと同じように、PL/SQLは、データベースのデータを問い合せ、変換して、更新することができます。 PL/SQLでは、例外処理、カプセル化、データ隠ぺいおよびオブジェクト指向のデータ型など、あらゆるソフトウェア・エンジニアリング機能が提供されているため、設計およびデバッグ時間を節約できます。

PL/SQLは、Oracle Formsなどのツールを拡張します。 これらのツールでPL/SQLを使用すると、使い慣れた言語の構造体を使用してアプリケーションを構築できます。 たとえば、複数のトリガー・ステップ、マクロまたはユーザー・イグジットを使用するかわりに、Oracle Formsトリガーの中でPL/SQLブロック全体を使用できます。 また、PL/SQLはどの環境でも同じです。 Oracleのある1つのツール製品で習得したPL/SQLの知識は他のツールにも利用できます。

完全な移植性

PL/SQLで作成されたアプリケーションは、データベースが動作する任意のオペレーティング・システムおよびプラットフォームで実行できます。 したがって、PL/SQLを使用すると、様々な環境で再利用できる、移植性の高いプログラム・ライブラリを作成できます。

優れたセキュリティ

PL/SQLストアド・サブプログラムは、クライアントからサーバーへアプリケーション・コードを移動します。サーバーでは、コードの改ざんの防止、コード内の細部の隠ぺいおよびアクセスの制限が可能になります。 たとえば、表を更新するサブプログラムへのアクセス権をユーザーに付与して、表自体またはUPDATE文のテキストへのアクセス権は付与しないようにできます。 PL/SQLで作成されたトリガーは、データへの変更を制御および記録して、すべての変更がビジネス・ルールに従っていることを確認します。

PL/SQLのソース・ユニットのラップまたは隠ぺいの詳細は、付録A「PL/SQLのソース・コードのラップ」を参照してください。

事前定義パッケージへのアクセス

Oracleでは、様々な実用的な作業を実行するためにPL/SQLから起動できるAPIを定義した製品固有のパッケージを提供しています。 これらのパッケージには、データベースのトリガーを使用するためのDBMS_ALERT、オペレーティング・システムのテキスト・ファイルを読み書きするためのDBMS_FILEHypertext Transfer Protocol(HTTP)のコールアウトを実行するためのUTL_HTTP、PL/SQLブロックおよびサブプログラムの出力を表示するためのDBMS_OUTPUT、名前付きパイプを介して通信するためのDBMS_PIPEなどがあります。 これらのパッケージの詳細は、「製品固有のPL/SQLパッケージの概要」を参照してください。

Oracleが提供するパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

オブジェクト指向プログラミングのサポート

オブジェクト型は理想的なオブジェクト指向のモデル・ツールであり、それによって複雑なアプリケーションの構築に必要な費用と時間を節約できます。 オブジェクト型を使用すると、モジュール構造で維持および再利用が可能なソフトウェア構成要素を作成できるのみでなく、複数の異なるチームのプログラマが同時にソフトウェア構成要素を開発できます。

データに対する操作をカプセル化すると、オブジェクト型を使用してデータ・メンテナンスのためのコードをSQLスクリプトやPL/SQLブロックではなく、メソッドに入れることができます。 また、オブジェクト型を使用すれば、実装の細部が隠されるため、クライアント・プログラムに影響することなく細部を変更できます。

さらに、オブジェクト型を使用することで、現実のデータをモデル化できます。 複雑な実世界のエンティティと関係は、オブジェクト型に直接関連付けることができます。 この直接マッピングは、プログラムがシミュレートしている世界をより適切に反映するために役立ちます。 オブジェクト型の詳細は、『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』を参照してください。

WebアプリケーションおよびServer Pages開発のサポート

PL/SQLを使用すると、WebアプリケーションおよびServer Pages(PSP)を開発できます。 詳細は、「PL/SQLを使用してWebアプリケーションを作成する方法」および「PL/SQLを使用してServer Pagesを作成する方法」を参照してください。

PL/SQLの主な特長

PL/SQLでは、SQLのデータ操作機能と手続き型言語の処理機能の両方が利用できます。

SQLを使用して問題が解決できる場合、PL/SQLプログラムからSQL文を発行できます。新しいAPIを学習する必要はありません。

その他の手続き型プログラム言語と同様に、PL/SQLでは、定数と変数の宣言、プログラム・フローの制御、サブプログラムの定義、およびランタイム・エラーのトラップを行うこともできます。

複雑な問題を容易に理解できるサブプログラムに分割し、複数のアプリケーションで再利用できます。

ここでのトピック:

PL/SQLブロック

PL/SQLソース・プログラムの基本単位はブロックで、関連する宣言および文をグループ化します。

PL/SQLブロックは、キーワードDECLAREBEGINEXCEPTIONおよびENDで定義します。 これらのキーワードは、ブロックを宣言部、実行部、例外処理部に分けます。 このうち必ず存在する必要があるのは実行部のみです。

宣言はブロックの中で局所的に有効で、そのブロックの実行が完了すると消滅します。これによって、変数およびサブプログラムの名前空間が一杯になることを回避できます。

ブロックはネストできます。ブロックは実行可能文であるため、実行可能文を配置できる場所であれば別のブロックでも配置できます。

例1-1に、PL/SQLブロックの基本構造を示します。 構文の詳細は、「ブロック」を参照してください。

例1-1 PL/SQLブロック構造

DECLARE    -- Declarative part (optional)
  -- Declarations of local types, variables, & subprograms

BEGIN      -- Executable part (required)
  -- Statements (which can use items declared in declarative part)

[EXCEPTION -- Exception-handling part (optional)
  -- Exception handlers for exceptions raised in executable part]
END;

PL/SQLブロックは、SQL*PlusやEnterprise Managerなどの対話型ツールに送信するか、またはOracleプリコンパイラやOCIのプログラムに埋め込むことができます。 対話型ツールまたはプログラムによって、ブロックが1回だけ実行されます。 ブロックはデータベースには格納されません。

名前の付けられたPL/SQLブロック(サブプログラム)は、繰り返し起動できます(「PL/SQLサブプログラム」を参照)。


注意:

データベースに格納されないブロックは、ラベルがある場合でも無名ブロックと呼ばれます。

PL/SQLのエラー処理

PL/SQLでは、例外と呼ばれるエラー条件を、簡単に検出して処理できます。 エラーが発生すると、例外が呼び出されます。通常の実行は中止され、制御は任意のPL/SQLブロックの末尾に記述されている特別な例外処理部に移ります。 例外は、種類ごとにそれぞれ特定の例外ハンドラによって処理されます。

PL/SQLの例外処理は、C言語で使用されるような手動チェックとは異なり、すべての処理が成功したことを確認するためにチェックを挿入します。 そのかわりに、Java言語の例外処理メカニズムと同様、エラー・ルーチンへのチェックおよびコールは自動的に行われます。

変数やデータベース操作などに関連する特定の一般的なエラー条件の場合、事前定義の例外が自動的に呼び出されます。 たとえば、数値を0(ゼロ)で除算しようとすると、事前定義の例外ZERO_DIVIDEが自動的に呼び出されます。

エラーであると定義した条件に対して、または通常はORA-nエラー・メッセージが表示されるデータベース・エラーに対応するように、独自の例外を定義できます。 ユーザー定義のエラー条件が検出された場合は、RAISE文またはDBMS_STANDARD.RAISE_APPLICATION_ERRORプロシージャのいずれかを使用して例外を呼び出します。 例1-16の例外comm_missingを参照してください。 この例では、コミッションがNULLの場合は例外comm_missingが呼び出されます。

通常は、例外ハンドラをサブプログラムの最後に配置して、サブプログラム内のすべての場所で発生した例外を処理します。 例外が発生した部分から実行を継続するには、例外が発生する可能性があるコードをさらにBEGIN-ENDブロック内に入れ、そのコード用の例外ハンドラを含めます。 たとえば、NO_DATA_FOUNDが発生する可能性があるSQL文のグループや、DIVIDE_BY_ZEROが発生する可能性がある算術演算を、それぞれ個別のBEGIN-ENDブロックに含めます。 BEGIN-ENDブロックを配置してループ内に例外ハンドラを含めることで、ループの反復中に例外が発生しても、そのループの実行を継続できます。 例5-38を参照してください。

PL/SQLエラーの詳細は、「PL/SQLのランタイム・エラー処理の概要」を参照してください。 PL/SQLの警告の詳細は、「PL/SQLのコンパイル時の警告の概要」を参照してください。

PL/SQLの入出力

PL/SQLのほとんどの入出力(I/O)は、SQL文によるデータベース表へのデータの格納や、それらの表の問合せによるものです。 PL/SQLのその他のすべてのI/Oは、PL/SQLパッケージDBMS_OUTPUTなどのAPIによるものです。

DBMS_OUTPUTに渡される出力を表示するには、SQL*Plusなどの別のプログラムが必要です。 SQL*PlusでDBMS_OUTPUTの出力を表示するには、事前に、SQL*PlusコマンドSET SERVEROUTPUT ONを発行しておく必要があります。 SET SERVEROUTPUT ONの詳細は、『SQL*Plusユーザーズ・ガイドおよびリファレンス』を参照してください。

パッケージで提供されるI/O処理のその他のPL/SQL APIには、次のものがあります。

パッケージ PL/SQLでのパッケージの用途
HTFおよびHTP Webページへの出力の表示
DBMS_PIPE PL/SQLとオペレーティング・システム・コマンドとの間での情報の受け渡し
UTL_FILE オペレーティング・システム・ファイルの読取りおよび書込み
UTL_HTTP Webサーバーとの通信
UTL_SMTP メール・サーバーとの通信

前述のAPIのいくつかは出力を表示するだけでなく入力も受け入れますが、キーボードから入力されたデータを直接受け入れることはできません。 その場合は、SQL*PlusコマンドPROMPTおよびACCEPTを使用します。


参照:

  • SQL*PlusコマンドPROMPTの詳細は、『SQL*Plusユーザーズ・ガイドおよびリファレンス』を参照してください。

  • SQL*PlusコマンドACCEPTの詳細は、『SQL*Plusユーザーズ・ガイドおよびリファレンス』を参照してください。

  • すべてのPL/SQLパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。


PL/SQLの変数および定数

PL/SQLでは変数と定数を宣言し、SQL文とプロシージャ文の中で、式を使用可能な任意の場所で使用できます。 このため、他の文で定数と変数を参照するときは、事前に宣言する必要があります。 詳細は、「宣言」を参照してください。

ここでのトピック:

PL/SQL変数の宣言

PL/SQL変数は、CHARDATENUMBERなどの任意のSQLデータ型や、BOOLEANPLS_INTEGERなどのPL/SQL固有のデータ型を持つことができます。

例1-2では、複数のPL/SQL変数を宣言しています。 PL/SQL固有のデータ型もあれば、SQLデータ型もあります。

例1-2 PL/SQL変数の宣言

SQL> DECLARE
  2    part_number       NUMBER(6);     -- SQL data type
  3    part_name         VARCHAR2(20);  -- SQL data type
  4    in_stock          BOOLEAN;       -- PL/SQL-only data type
  5    part_price        NUMBER(6,2);   -- SQL data type
  6    part_description  VARCHAR2(50);  -- SQL data type
  7  BEGIN
  8    NULL;
  9  END;
 10  /

PL/SQL procedure successfully completed.

SQL>

PL/SQLデータ型の詳細は、第3章「PL/SQLのデータ型」を参照してください。

PL/SQLを使用すると、ネストした表、可変サイズの配列、レコードなどのコンポジット・データ型を宣言できます。 詳細は、第5章「PL/SQLのコレクションおよびレコードの使用」を参照してください。

変数への値の代入

変数に値を代入する方法は、次のとおりです。

  • 代入演算子(:=)を使用する方法(例1-3を参照)

  • データベース値を選択またはフェッチして代入する方法(例1-4を参照)

  • 値をOUTパラメータまたはIN OUTパラメータとしてサブプログラムに渡し、サブプログラム内で代入する方法(例1-5を参照)

例1-3 代入演算子を使用した変数への値の代入

SQL> DECLARE  -- You can assign values here
  2    wages          NUMBER;
  3    hours_worked   NUMBER := 40;
  4    hourly_salary  NUMBER := 22.50;
  5    bonus          NUMBER := 150;
  6    country        VARCHAR2(128);
  7    counter        NUMBER := 0;
  8    done           BOOLEAN;
  9    valid_id       BOOLEAN;
 10    emp_rec1       employees%ROWTYPE;
 11    emp_rec2       employees%ROWTYPE;
 12    TYPE commissions IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
 13    comm_tab       commissions;
 14
 15  BEGIN  -- You can assign values here too
 16     wages := (hours_worked * hourly_salary) + bonus;
 17     country := 'France';
 18     country := UPPER('Canada');
 19     done := (counter > 100);
 20     valid_id := TRUE;
 21     emp_rec1.first_name := 'Antonio';
 22     emp_rec1.last_name := 'Ortiz';
 23     emp_rec1 := emp_rec2;
 24     comm_tab(5) := 20000 * 0.15;
 25  END;
 26  /

PL/SQL procedure successfully completed.

SQL>

例1-4では、従業員の給料の10%が選択され、bonus変数に代入されます。 変数bonusを別の計算に使用したり、変数の値をデータベース表に挿入することができます。

例1-4 SELECT INTOを使用した変数への値の代入

SQL> DECLARE
  2    bonus   NUMBER(8,2);
  3    emp_id  NUMBER(6) := 100;
  4  BEGIN
  5    SELECT salary * 0.10 INTO bonus
  6      FROM employees
  7        WHERE employee_id = emp_id;
  8  END;
  9  /

PL/SQL procedure successfully completed.

SQL>

例1-5では、サブプログラムに変数new_salを渡し、そのサブプログラムで変数を更新しています。

例1-5 サブプログラムのパラメータとしての変数への値の代入

SQL> DECLARE
  2    new_sal  NUMBER(8,2);
  3    emp_id   NUMBER(6) := 126;
  4
  5    PROCEDURE adjust_salary (
  6      emp_id      NUMBER,
  7      sal IN  OUT NUMBER
  8    ) IS
  9      emp_job  VARCHAR2(10);
 10      avg_sal  NUMBER(8,2);
 11    BEGIN
 12      SELECT job_id INTO emp_job
 13        FROM employees
 14          WHERE employee_id = emp_id;
 15
 16      SELECT AVG(salary) INTO avg_sal
 17        FROM employees
 18          WHERE job_id = emp_job;
 19
 20      DBMS_OUTPUT.PUT_LINE ('The average salary for '
 21                            || emp_job
 22                            || ' employees: '
 23                            || TO_CHAR(avg_sal)
 24                           );
 25
 26      sal := (sal + avg_sal)/2;
 27    END;
 28
 29  BEGIN
 30    SELECT AVG(salary) INTO new_sal
 31      FROM employees;
 32
 33    DBMS_OUTPUT.PUT_LINE ('The average salary for all employees: '
 34                          || TO_CHAR(new_sal)
 35                         );
 36
 37    adjust_salary(emp_id, new_sal);
 38  END;
 39  /
The average salary for all employees: 6461.68
The average salary for ST_CLERK employees: 2785

PL/SQL procedure successfully completed.

SQL>

PL/SQL定数の宣言

PL/SQL定数の宣言はPL/SQL変数の宣言と似ていますが、キーワードCONSTANTを付ける点と、定数に直接値を代入する必要がある点が異なります。 次に例を示します。

credit_limit CONSTANT NUMBER := 5000.00;

後で定数に値を代入することはできません。

バインド変数

バインド変数は、データベースでSQL文を再使用できるようにすることによって、パフォーマンスを向上させます。

PL/SQLコードにSQLのINSERTUPDATEDELETEまたはSELECT文を埋め込むと、PL/SQLは、WHERE句およびVALUES句内の変数を自動的にバインド変数に変換します。 これらのSQL文は、同じコードが実行されるたびにデータベースによって再利用されます。 異なる変数値を持つ類似する文を実行する場合、パラメータを受け取り、それらのパラメータを文の適切な部分に代入してその文を発行するストアド・サブプログラムを起動することで、解析によるオーバーヘッドを低減できます。

バインド変数は、動的SQLの使用時にPL/SQLによって自動的には作成されませんが、明示的に指定することによって動的SQLとともに使用できます。

PL/SQLのデータの抽象化

データの抽象化によって、詳細な部分を必要以上に意識することなく、データの基本的なプロパティを操作できます。 データ構造を一度設計した後は、データ構造を操作するアルゴリズムの設計に集中できます。

ここでのトピック:

カーソル

カーソルとは、特定の文を処理する情報を保存しておく、SQLの特定のプライベート領域の名前です。 PL/SQLでは、明示カーソルおよび暗黙カーソルが使用できます。 PL/SQLでは、1行のみを戻す問合せを含む、一連の行にあるすべてのSQLデータ操作文に対して、暗黙的にカーソルが宣言されます。 複数行を戻す問合せの場合は、カーソルを明示的に宣言し、その行を個別に処理できます。 たとえば、例1-6では、明示カーソルを宣言します。

カーソルの詳細は、「PL/SQLでのカーソルの管理」を参照してください。

%TYPE属性

%TYPE属性は、変数またはデータベース列のデータ型を与えます。 これはデータベース値を保持する変数を宣言する場合に、特に便利です。 たとえば、employeesという名前の表にlast_nameという名前の列があるとします。 last_nameと同じデータ型の変数v_last_nameを宣言するには、ドット表記法と%TYPE属性を次のように使用します。

v_last_name employees.last_name%TYPE;

%TYPE属性を使用してv_last_nameを宣言することには2つのメリットがあります。 第1に、ユーザーはlast_nameの正確なデータ型を知る必要がありません。 第2に、last_nameのデータベース定義を変更した場合(文字列の長さを増やすなど)でも、v_last_nameのデータ型はそれに応じて実行時に変更されます。

%TYPEの詳細は、「%TYPE属性の使用」および「%TYPE属性」を参照してください。

%ROWTYPE属性

PL/SQLではデータのグループ化にレコードを使用します。 レコードは、データ値を格納できる複数の関連したフィールドから構成されます。 %ROWTYPE属性は、表中の行を表すレコード型を与えます。 レコードには、表から選択された行全体、あるいはカーソルまたはカーソル変数でフェッチされた行全体のデータを格納できます。 「カーソル」を参照してください。

行の中の列と、それに対応するレコード中のフィールドは、同じ名前と同じデータ型を持ちます。 次の例では、departments表の列と同じ名前およびデータ型のフィールドを持つdept_recという名前のレコードを宣言しています。

dept_rec departments%ROWTYPE; -- declare record variable

次に示すように、フィールドの値にアクセスするにはドット表記法を使用します。

v_deptid := dept_rec.department_id;

従業員の姓、給与、入社日および役職を取り出すカーソルを宣言する場合は、%ROWTYPEを使用して、同じ情報を格納するレコードを宣言できます。

例1-6FETCH文は、employees表のlast_name列の値をemployee_reclast_nameフィールドに、salary列の値をsalaryフィールドに、というように代入します。

例1-6 明示カーソルでの%ROWTYPEの使用

SQL> DECLARE
  2    CURSOR c1 IS
  3      SELECT last_name, salary, hire_date, job_id
  4        FROM employees
  5          WHERE employee_id = 120;
  6
  7     employee_rec c1%ROWTYPE;
  8
  9  BEGIN
 10    OPEN c1;
 11    FETCH c1 INTO employee_rec;
 12    DBMS_OUTPUT.PUT_LINE('Employee name: ' || employee_rec.last_name);
 13  END;
 14  /
Employee name: Weiss

PL/SQL procedure successfully completed.

SQL>

%ROWTYPEの詳細は、「%ROWTYPE属性の使用」および「%ROWTYPE属性」を参照してください。

コレクション

PL/SQLのコレクション型を使用すると、他の言語で使用される配列、セットおよびハッシュ表に類似した高水準のデータ型を宣言できます。 PL/SQLでは、配列型はVARRAY(可変サイズの配列)、セット型はネストした表、ハッシュ表は結合配列と呼ばれます。 各コレクションは、すべて同じ型の要素の順序付きグループです。 各要素には一意の添字が付いています。その番号によって、集合の中での要素の位置が決まります。 コレクションを宣言する場合は、TYPE定義を使用します。 「コレクション型の定義」を参照してください。

要素を参照するには、例1-7で示すように、カッコを使用した添字表記法を使用します。

例1-7 PL/SQLのコレクション型の使用

SQL> DECLARE
  2    TYPE staff_list IS TABLE OF employees.employee_id%TYPE;
  3    staff  staff_list;
  4    lname  employees.last_name%TYPE;
  5    fname  employees.first_name%TYPE;
  6  BEGIN
  7    staff := staff_list(100, 114, 115, 120, 122);
  8
  9    FOR i IN staff.FIRST..staff.LAST LOOP
 10      SELECT last_name, first_name INTO lname, fname
 11        FROM employees
 12          WHERE employees.employee_id = staff(i);
 13
 14       DBMS_OUTPUT.PUT_LINE (TO_CHAR(staff(i))
 15                             || ': '
 16                             || lname
 17                             || ', '
 18                             || fname
 19                            );
 20    END LOOP;
 21  END;
 22  /
100: King, Steven
114: Raphaely, Den
115: Khoo, Alexander
120: Weiss, Matthew
122: Kaufling, Payam

PL/SQL procedure successfully completed.

SQL>

コレクションはパラメータとして渡すこともできるため、サブプログラムは任意の数の要素を処理できます。コレクションを使用すると、バルクSQLと呼ばれるパフォーマンスの高い言語機能を使用して、データベース表からデータを出し入れできます。

コレクションの詳細は、第5章「PL/SQLのコレクションおよびレコードの使用」を参照してください。

レコード

レコードのデータ構造はコンポジット型で、フィールドには様々なデータ型を含めることができます。 レコードを使用すると、関連する項目を保持し、単一のパラメータでサブプログラムにこれらの項目を渡すことができます。 レコードを宣言する場合は、例1-8に示すように、TYPE定義を使用します。 「レコードの定義と宣言」を参照してください。

例1-8 レコード型の宣言

SQL> DECLARE
  2    TYPE timerec IS RECORD (
  3      hours   SMALLINT,
  4      minutes SMALLINT
  5    );
  6
  7    TYPE meeting_type IS RECORD (
  8      date_held  DATE,
  9      duration   timerec,  -- nested record
 10      location   VARCHAR2(20),
 11      purpose    VARCHAR2(50)
 12    );
 13
 14  BEGIN
 15    NULL;
 16  END;
 17  /

PL/SQL procedure successfully completed.

SQL>

%ROWTYPE属性を使用して、表の行または問合せの結果セットの行を表すレコードを宣言できます。フィールドの名前および型を指定する必要はありません。

レコードの詳細は、第5章「PL/SQLのコレクションおよびレコードの使用」を参照してください。

オブジェクト型

PL/SQLは、オブジェクト型を介したオブジェクト指向のプログラミングをサポートします。 オブジェクト型は、データを操作するために必要なサブプログラムとともにデータ構造をカプセル化します。 データ構造を形成する変数は、属性と呼ばれます。 属性を操作するサブプログラムは、メソッドと呼ばれます。

オブジェクト型によって、大規模なシステムが複数の論理エンティティに細分化されるため、複雑さが軽減されます。 これによって、モジュール構造を持ち、保持および再利用が可能なソフトウェア・コンポーネントを作成できます。 オブジェクト型の定義およびメソッドのコードは、データベースに格納されます。 これらのオブジェクト型のインスタンスは、表に格納するか、またはPL/SQLコード内で変数として使用できます。 例1-9に、銀行口座のオブジェクト型の定義を示します。

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

SQL> CREATE TYPE bank_account AS OBJECT (
  2    acct_number NUMBER(5),
  3    balance     NUMBER,
  4    status      VARCHAR2(10),
  5
  6    MEMBER PROCEDURE open
  7      (SELF IN OUT NOCOPY bank_account,
  8       amount IN NUMBER),
  9
 10    MEMBER PROCEDURE close
 11      (SELF IN OUT NOCOPY bank_account,
 12       num IN NUMBER,
 13       amount OUT NUMBER),
 14
 15    MEMBER PROCEDURE deposit
 16      (SELF IN OUT NOCOPY bank_account,
 17       num IN NUMBER,
 18       amount IN NUMBER),
 19
 20    MEMBER PROCEDURE withdraw
 21      (SELF IN OUT NOCOPY bank_account,
 22       num IN NUMBER,
 23       amount IN NUMBER),
 24
 25    MEMBER FUNCTION curr_bal (num IN NUMBER) RETURN NUMBER
 26  );
 27  /

Type created.

SQL>

オブジェクト型の詳細は、『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』を参照してください。

PL/SQLの制御構造

制御構造は、SQLに対して加えられたPL/SQLの最も重要な機能拡張です。 PL/SQLを使用すると、データベース内のデータを操作できるのみでなく、制御フロー文を使用してデータを処理できます。

ここでのトピック:

詳細は、第4章「PL/SQLの制御構造の使用」を参照してください。

条件制御

状況に応じてアクションを選択する必要のある場面はよくあります。 IF-THEN-ELSE文を使用すると、一連の文を条件に合わせて実行できます。 IF句で条件を検査します。THEN句で条件がTRUEの場合のアクションを定義し、ELSE句では条件がFALSEまたはNULLの場合のアクションを定義します。 例1-10に、IF-THEN-ELSEを使用して、従業員が現在の給与に基づいて受け取る給与の昇給額を決める場合の例を示します。

複数の値から、またはアクションの途中で選択するには、CASE構造体を使用できます。 CASE式では条件が評価され、各ケースの値が戻されます。 例1-10に示すように、CASE文では条件が評価され、ケースごとにアクションが実行されます。

例1-10 IF-THEN-ELSE文およびCASE文を使用した条件制御

SQL> DECLARE
  2     jobid      employees.job_id%TYPE;
  3     empid      employees.employee_id%TYPE := 115;
  4     sal        employees.salary%TYPE;
  5     sal_raise  NUMBER(3,2);
  6  BEGIN
  7    SELECT job_id, salary INTO jobid, sal
  8      FROM employees
  9        WHERE employee_id = empid;
 10
 11    CASE
 12      WHEN jobid = 'PU_CLERK' THEN
 13        IF sal < 3000 THEN
 14          sal_raise := .12;
 15        ELSE
 16          sal_raise := .09;
 17        END IF;
 18
 19      WHEN jobid = 'SH_CLERK' THEN
 20        IF sal < 4000 THEN
 21          sal_raise := .11;
 22        ELSE
 23          sal_raise := .08;
 24        END IF;
 25
 26      WHEN jobid = 'ST_CLERK' THEN
 27        IF sal < 3500 THEN
 28          sal_raise := .10;
 29        ELSE
 30          sal_raise := .07;
 31        END IF;
 32
 33      ELSE
 34        BEGIN
 35          DBMS_OUTPUT.PUT_LINE('No raise for this job: ' || jobid);
 36        END;
 37     END CASE;
 38
 39     UPDATE employees
 40       SET salary = salary + salary * sal_raise
 41         WHERE employee_id = empid;
 42  END;
 43  /

PL/SQL procedure successfully completed.

SQL>

問合せの結果を使用してアクションを選択する一連の文が、データベース・アプリケーションではよく使用されます。 また、関連するエントリが別の表に見つかった場合にのみ、行の挿入や削除を実行する一連の文もよく使用されます。 このような頻繁に使用される一連の文は、条件論理を使用して1つのPL/SQLブロックにまとめることができます。

反復制御

LOOP文を使用すると、一連の文を複数回実行できます。 一連の文の最初の文の前にキーワードLOOPを置き、最後の文の後にキーワードEND LOOPを置きます。 一連の文を連続的に繰り返す最も簡単な形式のループを次に示します。

LOOP
  -- sequence of statements
END LOOP;

FOR-LOOP文では、整数の範囲を指定し、範囲中のそれぞれの整数に対して一連の文を1回実行できます。 例1-11では、ループで100個の数値を挿入し、平方根、平方および平方和をデータベース表に格納します。

例1-11 FOR-LOOPの使用

SQL> CREATE TABLE sqr_root_sum (
  2    num NUMBER,
  3    sq_root NUMBER(6,2),
  4    sqr NUMBER,
  5    sum_sqrs NUMBER
  6  );

Table created.

SQL>
SQL> DECLARE
  2     s  PLS_INTEGER;
  3  BEGIN
  4    FOR i in 1..100 LOOP
  5      s := (i * (i + 1) * (2*i +1)) / 6;  -- sum of squares
  6
  7      INSERT INTO sqr_root_sum
  8        VALUES (i, SQRT(i), i*i, s );
  9    END LOOP;
 10  END;
 11  /

PL/SQL procedure successfully completed.

SQL>

WHILE-LOOP文は、ある一連の文を条件付きで実行します。 ループを反復する前に条件が評価されます。 条件がTRUEならば、一連の文が実行されてから、ループの先頭で制御が再開します。 条件がFALSEまたはNULLならば、ループは実行されず、制御は次の文に移ります。

例1-12では、従業員120より指揮系統内で上位にあり、給与が$15000より高い最初の従業員を検索しています。

例1-12 WHILE-LOOPを使用した制御

SQL> CREATE TABLE temp (
  2    tempid   NUMBER(6),
  3    tempsal  NUMBER(8,2),
  4    tempname VARCHAR2(25)
  5  );

Table created.

SQL>
SQL> DECLARE
  2    sal             employees.salary%TYPE := 0;
  3    mgr_id          employees.manager_id%TYPE;
  4    lname           employees.last_name%TYPE;
  5    starting_empid  employees.employee_id%TYPE := 120;
  6
  7  BEGIN
  8     SELECT manager_id INTO mgr_id
  9       FROM employees
 10         WHERE employee_id = starting_empid;
 11
 12     WHILE sal <= 15000 LOOP
 13       SELECT salary, manager_id, last_name INTO sal, mgr_id, lname
 14         FROM employees
 15           WHERE employee_id = mgr_id;
 16     END LOOP;
 17
 18     INSERT INTO temp
 19        VALUES (NULL, sal, lname);
 20
 21  EXCEPTION
 22    WHEN NO_DATA_FOUND THEN
 23      INSERT INTO temp VALUES (NULL, NULL, 'Not found');
 24  END;
 25  /

PL/SQL procedure successfully completed.

SQL>

これ以上の処理を望まない場合、または不可能な場合は、EXIT-WHEN文でループを終了できます。 EXIT文が見つかると、WHEN句の中の条件が評価されます。 条件がTRUEならば、ループは終了し、制御は次の文に移ります。 例1-13では、totalの値が25,000を超えたときにループが終了します。

同様に、CONTINUE-WHEN文は、この反復を続行する必要がない場合、ただちにループの次の反復に制御を移します。

例1-13 EXIT-WHEN文の使用

SQL> CREATE TABLE temp (
  2    tempid   NUMBER(6),
  3    tempsal  NUMBER(8,2),
  4    tempname VARCHAR2(25)
  5  );

Table created.

SQL>
SQL> DECLARE
  2    total    NUMBER(9) := 0;
  3    counter  NUMBER(6) := 0;
  4  BEGIN
  5    LOOP
  6      counter := counter + 1;
  7      total   := total + counter * counter;
  8      EXIT WHEN total > 25000;
  9    END LOOP;
 10
 11    DBMS_OUTPUT.PUT_LINE ('Counter: '
 12                          || TO_CHAR(counter)
 13                          || ' Total: '
 14                          || TO_CHAR(total)
 15                         );
 16  END;
 17  /
Counter: 42 Total: 25585

PL/SQL procedure successfully completed.

SQL>

順次制御

GOTO文を使用すると、無条件にラベルへ分岐します。 ラベルは、二重の山カッコで囲まれた未宣言の識別子で、実行可能文またはPL/SQLブロックの前に置く必要があります。 例1-14で示すように、GOTO文が実行されると、ラベルが付けられた文またはブロックに制御が移ります。

例1-14 GOTO文の使用

SQL> DECLARE
  2    total    NUMBER(9) := 0;
  3    counter  NUMBER(6) := 0;
  4  BEGIN
  5    <<calc_total>>
  6    counter := counter + 1;
  7    total := total + counter * counter;
  8
  9    IF total > 25000 THEN
 10      GOTO print_total;
 11    ELSE
 12      GOTO calc_total;
 13    END IF;
 14
 15    <<print_total>>
 16    DBMS_OUTPUT.PUT_LINE
 17      ('Counter: ' || TO_CHAR(counter) || ' Total: ' || TO_CHAR(total));
 18  END;
 19  /
Counter: 42 Total: 25585

PL/SQL procedure successfully completed.

SQL>

PL/SQLサブプログラム

PL/SQLサブプログラムは、例1-15doubleのように、一連のパラメータによって起動できる名前付きPL/SQLブロックです。 PL/SQLにはプロシージャとファンクションの2種類のサブプログラムがあります。 ファンクションは結果を戻します。

例1-15 PL/SQLプロシージャ

SQL> DECLARE
  2    in_string   VARCHAR2(100) := 'Test string';
  3    out_string  VARCHAR2(200);
  4
  5    PROCEDURE double (
  6      original    IN  VARCHAR2,
  7      new_string  OUT VARCHAR2
  8    ) AS
  9    BEGIN
 10      new_string := original || original;
 11    END;
 12
 13  BEGIN
 14    DBMS_OUTPUT.PUT_LINE ('in_string: ' || in_string);
 15    double (in_string, out_string);
 16    DBMS_OUTPUT.PUT_LINE ('out_string: ' || out_string);
 17  END;
 18  /
in_string: Test string
out_string: Test stringTest string

PL/SQL procedure successfully completed.

SQL>

ここでのトピック:

PL/SQLサブプログラムの詳細は、第8章「PL/SQLサブプログラムの使用」を参照してください。

スタンドアロンPL/SQLサブプログラム

SQL文CREATE PROCEDUREおよびCREATE FUNCTIONを使用して、スタンドアロン・サブプログラムをスキーマ・レベルで作成できます。 スタンドアロン・サブプログラムはデータベースでコンパイルおよび格納され、データベースに接続している複数のアプリケーションで使用できます。 起動されたサブプログラムはすぐにロードされ、処理されます。 サブプログラムは共有メモリー機能を使用するため、複数のユーザーが実行する場合でも、メモリーにはサブプログラムのコピーが1つのみロードされます。

例1-16では、従業員番号とボーナス額を受け入れ、その番号を使用してデータベース表から従業員のコミッション・パーセントを選択し、コミッション・パーセントを小数値に変換してからコミッション額をチェックするスタンドアロン・プロシージャを作成します。 コミッションがNULLの場合は例外が呼び出され、NULLでない場合は従業員の給与台帳レコードが更新されます。

例1-16 スタンドアロンPL/SQLプロシージャの作成

SQL> CREATE OR REPLACE PROCEDURE award_bonus (
  2    emp_id NUMBER, bonus NUMBER) AS
  3    commission    REAL;
  4    comm_missing  EXCEPTION;
  5  BEGIN
  6    SELECT commission_pct / 100 INTO commission
  7      FROM employees
  8        WHERE employee_id = emp_id;
  9
 10    IF commission IS NULL THEN
 11      RAISE comm_missing;
 12    ELSE
 13      UPDATE employees
 14        SET salary = salary + bonus*commission
 15          WHERE employee_id = emp_id;
 16    END IF;
 17  EXCEPTION
 18    WHEN comm_missing THEN
 19      DBMS_OUTPUT.PUT_LINE
 20        ('This employee does not receive a commission.');
 21      commission := 0;
 22    WHEN OTHERS THEN
 23      NULL;
 24  END award_bonus;
 25  /

Procedure created.

SQL>

PL/SQLサブプログラムは、SQL*PlusやEnterprise Managerなどの対話型ツール、OracleプリコンパイラやOCIのプログラム、別のPL/SQLサブプログラム、またはトリガーから起動できます。

CREATE PROCEDURE文の詳細は、「CREATE PROCEDURE文」を参照してください。

SQL文CREATE FUNCTIONの詳細は、「CREATE FUNCTION文」を参照してください。

例1-17では、例1-16のストアド・サブプログラムをCALL文を使用して起動し、次にブロック内から起動します。

例1-17 SQL*Plusからのスタンドアロン・プロシージャの起動

SQL> -- Invoke standalone procedure with CALL statement
SQL>
SQL> CALL award_bonus(179, 1000);
Call completed.

SQL>
SQL> -- Invoke standalone procedure from within block
SQL>
SQL> BEGIN
  2    award_bonus(179, 10000);
  3  END;
  4  /

PL/SQL procedure successfully completed.

SQL>

BEGIN-ENDブロックの使用は、様々な場合に推奨されます。 たとえば、CALL文を使用すると、PL/SQLサブプログラムでは処理されなかったORA-nエラーを除去できます。

PL/SQLサブプログラムの起動の例は、例8-8を参照してください。 CALL文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

トリガー

トリガーは、表、ビューまたはイベントに関連付けられているストアド・サブプログラムです。 トリガーは、複数のイベントが発生した際に、1回または複数回(INSERT文、UPDATE文またはDELETE文の影響を受けた行ごとに1回)起動できます。 トリガーは、イベントの前または後に起動できます。

例1-18のトリガーは、employees表の給与が更新されるたびに起動されます。 更新のたびに、トリガーはレコードをemp_audit表に書き込みます。 (例1-10では、このトリガーを起動します。)

例1-18 トリガーの作成

SQL> CREATE TABLE emp_audit (
  2    emp_audit_id  NUMBER(6),
  3    up_date       DATE,
  4    new_sal       NUMBER(8,2),
  5    old_sal       NUMBER(8,2)
  6  );

Table created.

SQL>
SQL> CREATE OR REPLACE TRIGGER audit_sal
  2    AFTER UPDATE OF salary
  3      ON employees
  4        FOR EACH ROW
  5  BEGIN
  6    INSERT INTO emp_audit
  7      VALUES(:old.employee_id, SYSDATE, :new.salary, :old.salary);
  8  END;
  9  /

Trigger created.

SQL>

トリガー詳細は、第9章「トリガーの使用」を参照してください。

PL/SQLパッケージ(PL/SQLで記述されたAPI)

PL/SQLパッケージは、論理的に関連のある型、変数、カーソルおよびサブプログラムを、パッケージと呼ばれるデータベース・オブジェクトにまとめることができます。 このパッケージは、SQL文がアクセスする、関連した一連のサブプログラムおよび型に対して単純かつ明快なインタフェースを定義します。

PL/SQLを使用すると、多くの事前定義パッケージにアクセスし(「事前定義パッケージへのアクセス」を参照)、独自のパッケージを作成できます。

通常、パッケージには仕様部と本体の2つの部分があります。

仕様部はApplication Program Interface(API)を定義し、ここでデータ型、定数、変数、例外、カーソル、サブプログラムなどが宣言されます。 パッケージ仕様部を作成するには、CREATE PACKAGE文を使用します。

本体には、カーソルのSQL問合せおよびサブプログラムのコードが含まれます。パッケージ本体を作成するには、CREATE PACKAGE BODY文を使用します。

例1-19emp_actionsパッケージには、employees表を更新する2つのプロシージャと情報を提供する1つのファンクションが含まれます。

例1-19 パッケージおよびパッケージ本体の作成

SQL> -- Package specification:
SQL>
SQL> CREATE OR REPLACE PACKAGE emp_actions AS
  2
  3    PROCEDURE hire_employee (
  4      employee_id     NUMBER,
  5      last_name       VARCHAR2,
  6      first_name      VARCHAR2,
  7      email           VARCHAR2,
  8      phone_number    VARCHAR2,
  9      hire_date       DATE,
 10      job_id          VARCHAR2,
 11      salary          NUMBER,
 12      commission_pct  NUMBER,
 13      manager_id      NUMBER,
 14      department_id   NUMBER
 15    );
 16
 17    PROCEDURE fire_employee (emp_id NUMBER);
 18
 19    FUNCTION num_above_salary (emp_id NUMBER) RETURN NUMBER;
 20  END emp_actions;
 21  /

Package created.

SQL> -- Package body:
SQL>
SQL> CREATE OR REPLACE PACKAGE BODY emp_actions AS
  2
  3    -- Code for procedure hire_employee:
  4
  5    PROCEDURE hire_employee (
  6      employee_id     NUMBER,
  7      last_name       VARCHAR2,
  8      first_name      VARCHAR2,
  9      email           VARCHAR2,
 10      phone_number    VARCHAR2,
 11      hire_date       DATE,
 12      job_id          VARCHAR2,
 13      salary          NUMBER,
 14      commission_pct  NUMBER,
 15      manager_id      NUMBER,
 16      department_id   NUMBER
 17    ) IS
 18    BEGIN
 19      INSERT INTO employees
 20        VALUES (employee_id,
 21                last_name,
 22                first_name,
 23                email,
 24                phone_number,
 25                hire_date,
 26                job_id,
 27                salary,
 28                commission_pct,
 29                manager_id,
 30                department_id);
 31    END hire_employee;
 32
 33    -- Code for procedure fire_employee:
 34
 35    PROCEDURE fire_employee (emp_id NUMBER) IS
 36    BEGIN
 37      DELETE FROM employees
 38        WHERE employee_id = emp_id;
 39    END fire_employee;
 40
 41    -- Code for function num_above_salary:
 42
 43    FUNCTION num_above_salary (emp_id NUMBER) RETURN NUMBER IS
 44      emp_sal NUMBER(8,2);
 45      num_count NUMBER;
 46    BEGIN
 47      SELECT salary INTO emp_sal
 48        FROM employees
 49          WHERE employee_id = emp_id;
 50
 51      SELECT COUNT(*) INTO num_count
 52        FROM employees
 53          WHERE salary > emp_sal;
 54
 55      RETURN num_count;
 56    END num_above_salary;
 57  END emp_actions;
 58  /

Package body created.

SQL>

パッケージの名前と、サブプログラムの名前およびパラメータのみを知っていれば、パッケージ・サブプログラムを起動できます(したがって、起動するアプリケーションに影響を与えずに、パッケージ本体で実装の詳細を変更できます)。

例1-20では、emp_actionsパッケージのプロシージャhire_employeeおよびfire_employeeを起動します。

例1-20 パッケージのプロシージャの起動

SQL> CALL emp_actions.hire_employee (300, 'Belden', 'Enrique',
  2    'EBELDEN', '555.111.2222',
  3    '31-AUG-04', 'AC_MGR', 9000,
  4    .1, 101, 110);

Call completed.

SQL> BEGIN
  2    DBMS_OUTPUT.PUT_LINE
  3      ('Number of employees with higher salary: ' ||
  4        TO_CHAR(emp_actions.num_above_salary(120)));
  5
  6    emp_actions.fire_employee(300);
  7  END;
  8  /
Number of employees with higher salary: 34

PL/SQL procedure successfully completed.

SQL>

パッケージはデータベースに格納され、複数のアプリケーションで共有できます。 パッケージ・サブプログラムを初めて起動すると、パッケージ全体がロードされてメモリーにキャッシュされるため、それ以降の起動ではディスクI/Oが減少します。 このように、パッケージによって再利用が促進され、複数のユーザーおよび複数のアプリケーションが存在する環境でのパフォーマンスが向上します。

パッケージの詳細は、第10章「PL/SQLパッケージの使用」を参照してください。

条件付きコンパイル

PL/SQLでは条件付きコンパイルが提供され、ソース・コードを削除しなくても、PL/SQLアプリケーションの機能をカスタマイズできます。 たとえば、次のことが可能です。

  • 最新のリリースのデータベースでは最新の機能を利用し、古いリリースのデータベースに対しては、新しい機能を無効にしてそのアプリケーションを実行します。

  • 開発環境ではデバッグ機能またはトレース機能をアクティブ化し、本番サイトでの実行では、アプリケーション内でその機能を隠ぺいします。

詳細は、「条件付きコンパイル」を参照してください。

埋込みSQL文

PL/SQLを使用したSQL問合せの処理は、他の言語を使用したファイルの処理と似ています。 たとえば、Perlプログラムは、ファイルをオープンして内容を読み取り、各行を処理した後ファイルをクローズします。 同様に、PL/SQLプログラムも、例1-21に示すとおり、問合せを発行し、結果セットから取り出した行を処理します。

例1-21 LOOPでの問合せ結果の処理

SQL> BEGIN
  2    FOR someone IN (SELECT * FROM employees WHERE employee_id < 120)
  3    LOOP
  4      DBMS_OUTPUT.PUT_LINE('First name = ' || someone.first_name ||
  5                           ', Last name = ' || someone.last_name);
  6    END LOOP;
  7  END;
  8  /
First name = Steven, Last name = King
First name = Neena, Last name = Kochhar
First name = Lex, Last name = De Haan
First name = Alexander, Last name = Hunold
First name = Bruce, Last name = Ernst
First name = David, Last name = Austin
First name = Valli, Last name = Pataballa
First name = Diana, Last name = Lorentz
First name = Nancy, Last name = Greenberg
First name = Daniel, Last name = Faviet
First name = John, Last name = Chen
First name = Ismael, Last name = Sciarra
First name = Jose Manuel, Last name = Urman
First name = Luis, Last name = Popp
First name = Den, Last name = Raphaely
First name = Alexander, Last name = Khoo
First name = Shelli, Last name = Baida
First name = Sigal, Last name = Tobias
First name = Guy, Last name = Himuro
First name = Karen, Last name = Colmenares

PL/SQL procedure successfully completed.

SQL>

このような単純なループを使用するか、または問合せ、データの取出しおよび処理の終了を行う個別の文を使用して処理を正確に制御することができます。

PL/SQLのアーキテクチャ

ここでのトピック:

PL/SQLエンジン

PL/SQLコンパイルおよび実行時システムは、PL/SQLユニットをコンパイルして実行するエンジンです。 このエンジンは、データベースにインストールすることも、Oracle Formsのようなアプリケーション開発ツールにインストールすることもできます。

どちらの環境でも、PL/SQLエンジンは任意の適切なPL/SQLユニットを入力として受け入れます。 図1-2に示すように、SQLエンジンはプロシージャ文のみを実行し、SQL文をデータベースのSQLエンジンに送信します。

図1-2 PL/SQLエンジン

PL/SQLエンジン
「図1-2 PL/SQLエンジン」の説明

通常、PL/SQLユニットはデータベースによって処理されます。

アプリケーション開発ツールは、PL/SQLユニットを処理する際に、それらをローカルのPL/SQLエンジンに渡します。 PL/SQLユニットにSQL文がない場合、ローカルのエンジンがPL/SQLユニット全体を処理します。 アプリケーション開発ツールが条件制御や反復制御を活用できる場合は、この機能が特に便利です。

たとえば、Oracle Formsアプリケーションは、フィールド・エントリの値のテストや単純な計算のためにSQL文を頻繁に使用します。 SQLのかわりにPL/SQLを使用すると、これらのアプリケーションはデータベースへのコールを回避できます。

PL/SQLユニットおよびコンパイル・パラメータ

PL/SQLユニットは、次のいずれかです。

  • PL/SQLブロック

  • FUNCTION

  • PACKAGE

  • PACKAGE BODY

  • PROCEDURE

  • TRIGGER

  • TYPE

  • TYPE BODY

PL/SQLユニットは、PL/SQLコンパイル・パラメータ(データベース初期化パラメータのカテゴリ)によって影響を受けます。 異なるPL/SQLユニット(パッケージの仕様部や本体など)に、異なるコンパイル・パラメータ設定を含めることができます。

表1-1に、PL/SQLコンパイル・パラメータとその説明を示します。 これらのパラメータの詳細は、『Oracle Databaseリファレンス』を参照してください。

これらのパラメータの値を表示するには、静的データ・ディクショナリ・ビュー ALL_PLSQL_OBJECT_SETTINGSを使用します。 このビューの詳細は、『Oracle Databaseリファレンス』を参照してください。

表1-1 PL/SQLコンパイル・パラメータ

パラメータ 説明

PLSCOPE_SETTINGS 1 

コンパイル時のコレクション、相互参照、およびPL/SQLソース・コードの識別子データの格納を制御します。 PL/Scopeツール(『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』を参照)によって使用されます。

PLSQL_CCFLAGS  1 

各PL/SQLユニットの条件付きコンパイルを独立して制御できます。

PLSQL_CODE_TYPE  1 

PL/SQLユニットのコンパイル・モードINTERPRETED(デフォルト)またはNATIVEを指定します。

PLSQL_OPTIMIZE_LEVELによって設定された)最適化レベルが2より小さい場合:

  • コンパイラは、PLSQL_CODE_TYPEに関係なく、解釈済コードを生成します。

  • NATIVEを指定した場合、コンパイラはNATIVEが無視されたことを警告します。

PLSQL_DEBUG  1 

PL/SQLユニットをデバッグ用にコンパイルするかどうかを指定します。 表の後の注意を参照してください。

PLSQL_NATIVE_LIBRARY_DIR

効果はありません。 表の後の注意を参照してください。

PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT

効果はありません。 表の後の注意を参照してください。

PLSQL_OPTIMIZE_LEVEL  1 

PL/SQLユニットのコンパイルで使用される最適化レベルを指定します(レベルを高くすると、コンパイラでより多くのPL/SQLユニットの最適化が試行されます。

PLSQL_OPTIMIZE_LEVEL=1の場合、PL/SQLユニットはデバッグ用にコンパイルされます。

PLSQL_WARNINGS  1 

PL/SQLコンパイラによる警告メッセージのレポートを有効または無効にし、エラーとして表示する警告メッセージを指定します。

NLS_LENGTH_SEMANTICS  1 

バイト長セマンティクスまたは文字長セマンティクスのいずれかを使用して、CHARおよびVARCHAR2列を作成できます。


1このパラメータのコンパイル時の値は、PL/SQLユニットのメタデータとともに格納されます。


注意:

次のコンパイル・パラメータは非推奨となっており、今後のOracle Databaseリリースでは使用できない場合があります。
  • PLSQL_DEBUG

    リリース11.1では、これはリリース10.2の場合と同じ効果(表1-1を参照)がありますが、コンパイラによって、これが非推奨であることが警告されます。

    PLSQL_DEBUGのかわりに、PLSQL_OPTIMIZE_LEVEL=1を使用することをお薦めします。

  • PLSQL_NATIVE_LIBRARY_DIR

    リリース11.1の場合、効果はありません。 コンパイラによって、これが非推奨であることが警告されます。

  • PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT

    リリース11.1の場合、効果はありません。 コンパイラによって、これが非推奨であることが警告されます。


表1-1のほとんどのパラメータのコンパイル時の値がPL/SQLユニットのメタデータとともに格納されており、プログラム・ユニットを明示的に再コンパイルする際にその値を再利用できます。この再利用を行うには、次の手順を実行します。

  1. 次のいずれかの文を使用してプログラム・ユニットを再コンパイルします。

    • ALTER FUNCTION COMPILE

    • ALTER PACKAGE COMPILE

    • ALTER PROCEDURE COMPILE

  2. 文にREUSE SETTINGS句を含めます。

    この句によって、既存の設定が保持され、文の他の場所に値が指定されていないパラメータの再コンパイルにその設定が使用されます。

SQL文CREATE OR REPLACEを使用してPL/SQLサブプログラムを明示的にコンパイルする場合、またはALTER COMPILE文にREUSE SETTINGS句を含めない場合、コンパイル・パラメータの値はセッション用の値になります。