14.10 CREATE PACKAGE BODY文
CREATE
PACKAGE
BODY
文は、データベースに1つの単位として格納される、関連するプロシージャやストアド・ファンクション、その他のプログラム・オブジェクトをカプセル化したコレクションである、ストアド・パッケージの本体を作成するか、または置き換えます。
パッケージ本体でこれらのオブジェクトを定義します。前述のCREATE
PACKAGE
文で定義したパッケージ仕様部で、これらのオブジェクトを宣言します。
一連のプロシージャやファンクションをスタンドアロンのスキーマ・オブジェクトとして作成するかわりの方法としてパッケージを使用する方法があります。
ここでのトピック
前提条件
自分のスキーマ内にパッケージを作成するか、または自分のスキーマ内のパッケージを置き換えるには、CREATE
PROCEDURE
システム権限が必要です。他のユーザーのスキーマ内にパッケージを作成または再作成する場合は、CREATE
ANY
PROCEDURE
システム権限が必要です。いずれの場合も、パッケージ本体をパッケージと同じスキーマに作成する必要があります。
CREATE
PACKAGE
BODY
文をデータベースのプリコンパイラ・プログラム内に埋め込むには、キーワードEND-EXEC
の後に特定の言語の埋込みSQL文の終了記号を付けて文を終了する必要があります。
構文
create_package_body ::=
initialize_section ::=
セマンティクス
create_package_body
OR REPLACE
パッケージ本体が存在する場合は、パッケージ本体を再作成し、再コンパイルします。
再定義する前のパッケージ本体に対する権限を付与されていたユーザーは、権限を再付与される必要なく、パッケージにアクセスできます。
[ EDITIONABLE | NONEDITIONABLE ]
このプロパティを指定しないと、パッケージ本体はパッケージ仕様部からEDITIONABLE
またはNONEDITIONABLE
を継承します。このプロパティを指定する場合は、パッケージ仕様部のプロパティと一致する必要があります。
plsql_package_body_source
schema
パッケージが含まれているスキーマの名前。デフォルト: 自分のスキーマ。
package_name
作成するパッケージの名前。
declare_section
パッケージ仕様部のすべてのカーソル定義およびサブプログラム宣言を配置します。対応するサブプログラム宣言と定義のヘッダーは、空白以外の一語一語が一致している必要があります。
パッケージ内からのみ参照できるプライベート項目を宣言および定義することもできます。
declare_sectionの制限
PRAGMA
AUTONOMOUS_TRANSACTION
は、ここには記述できません。
initialize_section
変数を初期化し、その他の1回のみの設定手順をすべて実行します。
例
例14-20 emp_mgmtパッケージ本体の作成
この文では、emp_mgmt
パッケージの本体を作成します。このパッケージは、「例14-19」で作成したものです。
CREATE OR REPLACE PACKAGE BODY emp_mgmt AS
tot_emps NUMBER;
tot_depts NUMBER;
FUNCTION hire
(last_name VARCHAR2, job_id VARCHAR2,
manager_id NUMBER, salary NUMBER,
commission_pct NUMBER, department_id NUMBER)
RETURN NUMBER IS new_empno NUMBER;
BEGIN
SELECT employees_seq.NEXTVAL
INTO new_empno
FROM DUAL;
INSERT INTO employees
VALUES (new_empno, 'First', 'Last','first.example@example.com',
'(415)555-0100',
TO_DATE('18-JUN-2002','DD-MON-YYYY'),
'IT_PROG',90000000,00, 100,110);
tot_emps := tot_emps + 1;
RETURN(new_empno);
END;
FUNCTION create_dept(department_id NUMBER, location_id NUMBER)
RETURN NUMBER IS
new_deptno NUMBER;
BEGIN
SELECT departments_seq.NEXTVAL
INTO new_deptno
FROM dual;
INSERT INTO departments
VALUES (new_deptno, 'department name', 100, 1700);
tot_depts := tot_depts + 1;
RETURN(new_deptno);
END;
PROCEDURE remove_emp (employee_id NUMBER) IS
BEGIN
DELETE FROM employees
WHERE employees.employee_id = remove_emp.employee_id;
tot_emps := tot_emps - 1;
END;
PROCEDURE remove_dept(department_id NUMBER) IS
BEGIN
DELETE FROM departments
WHERE departments.department_id = remove_dept.department_id;
tot_depts := tot_depts - 1;
SELECT COUNT(*) INTO tot_emps FROM employees;
END;
PROCEDURE increase_sal(employee_id NUMBER, salary_incr NUMBER) IS
curr_sal NUMBER;
BEGIN
SELECT salary INTO curr_sal FROM employees
WHERE employees.employee_id = increase_sal.employee_id;
IF curr_sal IS NULL
THEN RAISE no_sal;
ELSE
UPDATE employees
SET salary = salary + salary_incr
WHERE employee_id = employee_id;
END IF;
END;
PROCEDURE increase_comm(employee_id NUMBER, comm_incr NUMBER) IS
curr_comm NUMBER;
BEGIN
SELECT commission_pct
INTO curr_comm
FROM employees
WHERE employees.employee_id = increase_comm.employee_id;
IF curr_comm IS NULL
THEN RAISE no_comm;
ELSE
UPDATE employees
SET commission_pct = commission_pct + comm_incr;
END IF;
END;
END emp_mgmt;
パッケージ本体では、パッケージ仕様部で宣言された次のパブリック・プログラム・オブジェクトを定義します。
-
ファンクション
hire
およびcreate_dept
-
プロシージャ
remove_emp
、remove_dept
、increase_sal
およびincrease_comm
これらのオブジェクトはパッケージ仕様部で宣言されているため、パッケージ外部のアプリケーション・プログラム、プロシージャおよびファンクションでコールできます。たとえば、パッケージにアクセスできる場合は、increase_comm
プロシージャを起動するemp_mgmt
パッケージとは別にプロシージャincrease_all_comms
を作成できます。
これらのオブジェクトはパッケージ本体で定義されているため、依存するスキーマ・オブジェクトをデータベースで無効にしなくても、オブジェクトの定義を変更できます。たとえば、この後にhire
の定義を変更した場合、データベースで実行する前にincrease_all_comms
を再コンパイルする必要はありません。
また、この例のパッケージ本体では、プライベート・プログラム・オブジェクトである変数tot_emps
およびtot_depts
も宣言しています。これらのオブジェクトは、パッケージ仕様部ではなくパッケージ本体で宣言されているため、パッケージ内の他のオブジェクトからはアクセスできますが、パッケージの外部からはアクセスできません。たとえば、変数tot_depts
の値を明示的に変更するアプリケーションを開発することはできません。ただし、ファンクションcreate_dept
はパッケージの一部であるため、create_dept
でtot_depts
の値を変更できます。