すべてのプロダクト
Search
ドキュメントセンター

PolarDB:CREATE PACKAGE BODY

最終更新日:Dec 11, 2024

CREATE PACKAGE BODYステートメントは、保存済みパッケージの本文を作成します。 CREATE OR REPLACE PACKAGE BODYステートメントは、新しいパッケージボディを作成するか、既存のパッケージボディを置き換えます。 パッケージは、データベースアプリケーションロジックを整理およびカプセル化するための重要なツールです。 保存されたパッケージを適切に設計すると、コードの保守性、再利用性、パフォーマンスが向上します。

概要

CREATE PACKAGE BODYステートメントを使用して、関連するプロシージャ、ストアド関数、およびデータベースに一緒に格納された他のプログラムオブジェクトのカプセル化されたコレクションであるストアドパッケージのボディを作成できます。 パッケージ本体はこれらのオブジェクトを定義します。 CREATE packageステートメントを使用して定義されるパッケージ仕様は、これらのオブジェクトを宣言します。

構文

CREATE [ OR REPLACE ] PACKAGE BODY <package_name>
{ IS | AS }
  [ declaration; ] | [ forward_declaration ] [, ...]
  [ { PROCEDURE <proc_name>
      [ (<argname> [ IN | IN OUT | OUT ] <argtype> [ DEFAULT <value> ] [, ...]) ]
      [ STRICT ]
      [ LEAKPROOF ]
      [ PARALLEL { UNSAFE | RESTRICTED | SAFE } ]
      [ COST <execution_cost> ]
      [ ROWS <result_rows> ]
      [ SET <config_param> { TO <value> | = <value> | FROM CURRENT } ]
    { IS | AS }
        <program_body>
      END [ <proc_name> ];
    |
      FUNCTION <func_name>
      [ (<argname> [ IN | IN OUT | OUT ] <argtype> [ DEFAULT <value> ] [, ...]) ]
      RETURN <rettype> [ DETERMINISTIC ]
      [ STRICT ]
      [ LEAKPROOF ]
      [ PARALLEL { UNSAFE | RESTRICTED | SAFE } ]
      [ COST <execution_cost> ]
      [ ROWS <result_rows> ]
      [ SET <config_param> { TO <value> | = <value> | FROM CURRENT } ]
    { IS | AS }
        <program_body>
      END [ <func_name> ];
    }
  ] [, ...]
  [ BEGIN
      <statement>; [, ...] ]
  END [ <name> ]

Where forward_declaration:=

[ { PROCEDURE <proc_name>
  [ (<argname> [ IN | IN OUT | OUT ] <argtype> [ DEFAULT <value> ] [, ...])
  ] ;
|
    FUNCTION <func_name>
  [ (<argname> [ IN | IN OUT | OUT ] <argtype> [ DEFAULT <value> ] [, ...])
  ]
  RETURN <rettype> [ DETERMINISTIC ]; }]

Parameters

パラメーター

説明

package_name

パッケージの名前。

declaration

プライベート変数、型、カーソル、またはREF cursor宣言。

forward_declaration

フォワード宣言。実際に定義される前にプロシージャまたは関数を宣言するために使用されます。

モジュールでは、複数のサブプログラムを作成できます。 これらのサブプログラムが互いにコールする場合、各サブプログラムはフォワード宣言を必要とする。 サブプログラムは、呼び出す前に宣言する必要があります。 特定の定義なしでフォワード宣言を使用してサブプログラムを宣言できます。 forward宣言と対応する定義は、同じコードブロック内にある必要があります。

proc_name

パブリックストアドプロシージャの名前。

func_name

パブリック関数の名前。

STRICT

STRICTキーワードを使用して、関数がNULLパラメーターで呼び出されたときに実行されないように指定できます。 代わりに、関数はNULLを返します。

LEAKPROOF

LEAKPROOFキーワードを使用して、戻り値以外のパラメーターに関する詳細情報を表示しないように指定できます。

PARALLEL { UNSAFE | RESTRICTED | SAFE }

PARALLEL句は、パラレルスキャン (パラレルモード) を有効にします。 シーケンシャルスキャンとは異なり、並列スキャンは複数のワーカーを使用して、クエリ中に関係を並列にスキャンします。 有効な値:

  • UNSAFE (デフォルト): ストアドプロシージャまたは関数は並列モードでは実行できません。 このようなストアドプロシージャまたは関数がSQL文に存在する場合は, 強制的に逐次実行プランが使用されます。

  • RESTRICTED: ストアドプロシージャまたは関数は並列モードで実行できますが、実行は並列グループリーダーに制限されます。 特定の関係に関する資格にパラレル制限されたコンテンツがある場合、その関係がパラレル実行の際に選択されることはありません。

  • SAFE: ストアドプロシージャまたは関数は、制限なしに並列モードで実行できます。

execution_cost

関数の推定実行コスト。 それは正の数でなければなりません。 単位は cpu_operator_cost です。 関数がセットを返す場合、返された各行のコストを示します。 デフォルト値は 0.0025 です。

result_rows

関数が返すとプランナーが予想する行の推定数。 既定値は 1000 です。

SET

SET句を使用して、関数の期間のパラメーター値を指定できます。 有効な値:

  • config_param: パラメータ名を指定します。

  • value: パラメーター値を指定します。

  • FROM CURRENT: 関数の終了時にパラメーター値が復元されます。

program_body

関数またはストアドプロシージャの本体を構成するプラグマ、宣言、およびPL/SQLステートメント。 宣言は、変数、タイプ、REF CURSOR、およびサブプログラム宣言を含むことができる。

argname

パラメータの名前。

IN | IN OUT | OUT

パラメーターのタイプ。 有効な値:

argtype

プログラム引数のデータタイプ。

DEFAULT value

入力引数のデフォルト値。

rettype

返されるデータ型。

DETERMINISTIC

DETERMINISTIC を使用すると、同じ引数値が指定されている場合、関数が常に同じ結果を返すように指定できます。 DETERMINISTIC 関数はデータベースを変更しません。

PL/SQLステートメント。 パッケージが初めて参照される場合、パッケージ初期化セクションのステートメントはセッションごとに1回実行されます。

次の例は、パッケージの作成方法と使用方法を示しています。

  1. テストテーブルを作成します。

    CREATE TABLE employees (
        emp_id     NUMBER PRIMARY KEY,
        first_name VARCHAR2(50),
        last_name  VARCHAR2(50),
        salary     NUMBER,
        department VARCHAR2(50)
    );
  2. パッケージヘッダーを作成します。

    CREATE OR REPLACE PACKAGE Employee_Pkg AS
        -- Constant
        MAX_SALARY CONSTANT NUMBER := 100000;
    
        -- Procedure declaration
        PROCEDURE Add_Employee(
            p_emp_id     IN NUMBER,
            p_first_name IN VARCHAR2,
            p_last_name  IN VARCHAR2,
            p_salary     IN NUMBER
        );
    
        PROCEDURE Update_Salary(
            p_emp_id     IN NUMBER,
            p_new_salary IN NUMBER
        );
    
        -- Function declaration
        FUNCTION Get_Employee_Name(
            p_emp_id IN NUMBER
        ) RETURN VARCHAR2;
    
        FUNCTION Get_Employee_Department(
            p_emp_id IN NUMBER
        ) RETURN VARCHAR2;
    END Employee_Pkg;
  3. パッケージ本体を作成します。

    CREATE OR REPLACE PACKAGE BODY Employee_Pkg AS
    
        -- Private variable
        g_total_employees NUMBER := 0;
    
        -- Procedure implementation
        PROCEDURE Add_Employee(
            p_emp_id     IN NUMBER,
            p_first_name IN VARCHAR2,
            p_last_name  IN VARCHAR2,
            p_salary     IN NUMBER
        ) IS
        BEGIN
            INSERT INTO employees (emp_id, first_name, last_name, salary)
            VALUES (p_emp_id, p_first_name, p_last_name, p_salary);
            g_total_employees := g_total_employees + 1;
        END Add_Employee;
    
        PROCEDURE Update_Salary(
            p_emp_id     IN NUMBER,
            p_new_salary IN NUMBER
        ) IS
        BEGIN
            IF p_new_salary > MAX_SALARY THEN
                RAISE_APPLICATION_ERROR(-20001, 'Salary exceeds maximum allowed.');
            END IF;
            UPDATE employees
            SET salary = p_new_salary
            WHERE emp_id = p_emp_id;
        END Update_Salary;
    
        -- Function implementation
        FUNCTION Get_Employee_Name(
            p_emp_id IN NUMBER
        ) RETURN VARCHAR2 IS
            v_name VARCHAR2(100);
        BEGIN
            SELECT first_name || ' ' || last_name
            INTO v_name
            FROM employees
            WHERE emp_id = p_emp_id;
            RETURN v_name;
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN 'Employee Not Found';
        END Get_Employee_Name;
    
        FUNCTION Get_Employee_Department(
            p_emp_id IN NUMBER
        ) RETURN VARCHAR2 IS
            v_department VARCHAR2(100);
        BEGIN
            SELECT department
            INTO v_department
            FROM employees
            WHERE emp_id = p_emp_id;
            RETURN v_department;
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN 'Not Assigned';
        END Get_Employee_Department;
    
    END Employee_Pkg;
  4. パッケージを使用します。

    DECLARE
        v_name       VARCHAR2(100);
        v_department VARCHAR2(100);
    BEGIN
        Employee_Pkg.Add_Employee(
            p_emp_id     => 1001,
            p_first_name => 'Jane',
            p_last_name  => 'Smith',
            p_salary     => 60000
        );
    
        Employee_Pkg.Add_Employee(
            p_emp_id     => 1002,
            p_first_name => 'John',
            p_last_name  => 'Doe',
            p_salary     => 55000
        );
    
        Employee_Pkg.Update_Salary(
            p_emp_id     => 1001,
            p_new_salary => 65000
        );
    
        v_name := Employee_Pkg.Get_Employee_Name(1001);
        v_department := Employee_Pkg.Get_Employee_Department(1001);
        DBMS_OUTPUT.PUT_LINE('NAME: ' || v_name);
        DBMS_OUTPUT.PUT_LINE('DEPARTMENT: ' || v_department);
    END;