サブプログラムの各部

サブプログラムの先頭には、その名前およびオプションのパラメータ・リストを指定するサブプログラムのヘッダーがあります。

無名ブロックと同様に、サブプログラムには次の部分があります。

  • 宣言部(オプション)

    この部分では、ローカル型、カーソル、定数、変数、例外およびネストしたサブプログラムを宣言および定義します。これらの項目は、サブプログラムの実行が完了すると消滅します。

    この部分は、プラグマを指定することもできます。

    ノート:

    無名ブロックの宣言部とは異なり、サブプログラムの宣言部は、キーワードDECLAREでは始まりません。

  • 実行部(必須)

    この部分には、値の代入、実行の制御およびデータの操作を実行する1つ以上の文が含まれています。(アプリケーション設計プロセスの初期段階では、例5-31に示すとおり、この部分にNULL文のみを含めることも可能です。)

  • 例外処理部(オプション)

    この部分には、ランタイム・エラーを処理するコードが含まれています。

ここでのトピック

関連項目:

例9-1 単純なPL/SQLプロシージャの宣言、定義および起動

この例では、無名ブロックでプロシージャの宣言と定義を同時に行い、そのプロシージャを3回起動しています。3回目の起動では、プロシージャの例外処理部で処理される例外が呼び出されています。

DECLARE
  first_name employees.first_name%TYPE;
  last_name  employees.last_name%TYPE;
  email      employees.email%TYPE;
  employer   VARCHAR2(8) := 'AcmeCorp';
 
  -- Declare and define procedure
 
  PROCEDURE create_email (  -- Subprogram heading begins
    name1   VARCHAR2,
    name2   VARCHAR2,
    company VARCHAR2
  )                         -- Subprogram heading ends
  IS
                            -- Declarative part begins
    error_message VARCHAR2(30) := 'Email address is too long.';
  BEGIN                     -- Executable part begins
    email := name1 || '.' || name2 || '@' || company;
  EXCEPTION                      -- Exception-handling part begins
    WHEN VALUE_ERROR THEN
      DBMS_OUTPUT.PUT_LINE(error_message);
  END create_email;
 
BEGIN
  first_name := 'John';
  last_name  := 'Doe';
 
  create_email(first_name, last_name, employer);  -- invocation
  DBMS_OUTPUT.PUT_LINE ('With first name first, email is: ' || email);
 
  create_email(last_name, first_name, employer);  -- invocation
  DBMS_OUTPUT.PUT_LINE ('With last name first, email is: ' || email);
 
  first_name := 'Elizabeth';
  last_name  := 'MacDonald';
  create_email(first_name, last_name, employer);  -- invocation
END;
/

結果:

With first name first, email is: John.Doe@AcmeCorp
With last name first, email is: Doe.John@AcmeCorp
Email address is too long.

ファンクションの追加部分

ファンクションの構造は、プロシージャと同じですが、次の点が異なります。

  • ファンクションのヘッダーには、ファンクションが戻す値のデータ型を指定するRETURNが含まれている必要があります。(プロシージャのヘッダーには、RETURN句を含めることはできません。)

  • ファンクションの実行部では、すべての実行パスがRETURNへ導かれる必要があります。そうではない場合、PL/SQLコンパイラによってコンパイル時に警告が発行されます。(プロシージャでは、RETURN文はオプションであり、推奨されません。詳細は、「RETURN文」を参照してください。)

  • ファンクションの宣言には、次に示すオプションを含めることができます。

オプション 説明

DETERMINISTICオプション

オプティマイザが冗長なファンクションの起動を回避するために役立ちます。

PARALLEL_ENABLEオプション

ファンクションのパラレル実行を可能にし、パラレルDML評価の同時セッションで安全に使用できるようにします。

PIPELINEDオプション

行ソースとして使用するためにテーブル・ファンクションをパイプライン化します。

RESULT_CACHEオプション

PL/SQLファンクション結果キャッシュに、ファンクションの結果を格納します。

関連項目:

例9-2 単純なPL/SQLファンクションの宣言、定義および起動

この例では、無名ブロックでファンクションの宣言と定義を同時に行い、そのファンクションを起動しています。

DECLARE
  -- Declare and define function

  FUNCTION square (original NUMBER)   -- parameter list
    RETURN NUMBER                     -- RETURN clause
  AS
                                      -- Declarative part begins
    original_squared NUMBER;
  BEGIN                               -- Executable part begins
    original_squared := original * original;
    RETURN original_squared;          -- RETURN statement
  END;
BEGIN
  DBMS_OUTPUT.PUT_LINE(square(100));  -- invocation
END;
/

結果:

10000

RETURN文

RETURN文は、サブプログラムまたはこの文を含む無名ブロックの実行を即座に終了させます。サブプログラムまたは無名ブロックでは、複数のRETURN文を使用できます。

ここでのトピック

ファンクションのRETURN文

ファンクションでは、すべての実行パスがRETURN文に続き、すべてのRETURN文が式を指定している必要があります。RETURN文は、ファンクション識別子に式の値を代入し、起動元に制御を戻します(ここで、起動直後に実行が再開します)。

ノート:

パイプライン・テーブル・ファンクションでは、RETURN文で式を指定する必要はありません。パイプライン・テーブル・ファンクションの各部の詳細は、「パイプライン・テーブル・ファンクションの作成」を参照してください。

例9-3では、無名ブロックで同じファンクションを2回起動しています。1回目では、RETURN文は起動元の文の内部に制御を戻します。2回目では、RETURN文は起動元の文の直後の文に制御を戻します。

例9-4では、ファンクションに複数のRETURN文が含まれますが、パラメータが0または1でない場合、実行パスがRETURN文へ導かれません。このファンクションは、コンパイル時に「PLW-05005: サブプログラムFは、行11に値なしで戻ります」という警告が発生します。

例9-5は、例9-4と同様ですが、ELSE句が追加されています。すべての実行パスがRETURN文へ導かれるため、ファンクションのコンパイル時に警告PLW-05005は発生しません。

例9-3 ファンクション内にあるRETURN文の後での実行の再開

DECLARE
  x INTEGER;
 
  FUNCTION f (n INTEGER)
  RETURN INTEGER
  IS
  BEGIN
    RETURN (n*n);
  END;
 
BEGIN
  DBMS_OUTPUT.PUT_LINE (
    'f returns ' || f(2) || '. Execution returns here (1).'
  );
  
  x := f(2);
  DBMS_OUTPUT.PUT_LINE('Execution returns here (2).');
END;
/

結果:

f returns 4. Execution returns here (1).Execution returns here (2).

例9-4 RETURN文へ導かれない実行パスを含むファンクション

CREATE OR REPLACE FUNCTION f (n INTEGER)
  RETURN INTEGER
  AUTHID DEFINER
IS
BEGIN
  IF n = 0 THEN
    RETURN 1;
  ELSIF n = 1 THEN
    RETURN n;
  END IF;
END;
/

例9-5 すべての実行パスがRETURN文へ導かれるファンクション

CREATE OR REPLACE FUNCTION f (n INTEGER)
  RETURN INTEGER
  AUTHID DEFINER
IS
BEGIN
  IF n = 0 THEN
    RETURN 1;
  ELSIF n = 1 THEN
    RETURN n;
  ELSE
    RETURN n*n;
  END IF;
END;
/
BEGIN
  FOR i IN 0 .. 3 LOOP
    DBMS_OUTPUT.PUT_LINE('f(' || i || ') = ' || f(i));
  END LOOP;
END;
/

結果:

f(0) = 1
f(1) = 1
f(2) = 4
f(3) = 9

プロシージャのRETURN文

プロシージャでは、RETURN文は起動元に制御を戻します。ここで、起動すると実行が即座に再開します。RETURN文では、式を指定できません。

例9-6では、RETURN文は、起動元の文の直後の文に制御を戻しています。

例9-6 プロシージャ内にあるRETURN文の後での実行の再開

DECLARE
  PROCEDURE p IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('Inside p');
    RETURN;
    DBMS_OUTPUT.PUT_LINE('Unreachable statement.');
  END;
BEGIN
  p;
  DBMS_OUTPUT.PUT_LINE('Control returns here.');
END;
/

結果:

Inside p
Control returns here.

無名ブロックのRETURN文

無名ブロックでは、RETURN文によってそのブロックおよびすべての外側のブロックが終了されます。RETURN文では、式を指定できません。

例9-7では、RETURN文によって、内側と外側の両方のブロックが終了されています。

例9-7 無名ブロック内にあるRETURN文の後での実行の再開

BEGIN
  BEGIN
    DBMS_OUTPUT.PUT_LINE('Inside inner block.');
    RETURN;
    DBMS_OUTPUT.PUT_LINE('Unreachable statement.');
  END;
  DBMS_OUTPUT.PUT_LINE('Inside outer block. Unreachable statement.');
END;
/

結果:

Inside inner block.