Oracle PL/SQLパッケージ: タイプ、仕様、本体 [例]

⚡ スマートサマリー

PL/SQLパッケージは、関連するプロシージャ、関数、変数、カーソル、例外を、仕様と本体を持つ1つのスキーマオブジェクトにグループ化します。仕様は公開インターフェースを宣言し、本体はプライベートな実装を保持することで、モジュール性とパフォーマンスを向上させます。

  • 📦 パッケージ定義: パッケージとは論理的なグループですping 関連するサブプログラムとオブジェクトをコンパイルし、単一のデータベースオブジェクトとして格納します。
  • ???? パッケージ仕様: パッケージ外部からアクセス可能なパブリック変数、カーソル、型、例外、プロシージャ、および関数を宣言します。
  • 🧱 パッケージ本体: 仕様で宣言されているすべての要素に加え、パッケージ内部からのみ呼び出し可能なプライベート要素を定義します。
  • 🔁 オーバーロード: パラメータ番号、パラメータ型、または戻り値の型が異なる場合でも、複数のサブルーチンが同じ名前を共有することがあります。
  • 🔗 参照と依存関係: 公開要素はパッケージ名.要素名という形式で呼び出され、本体は仕様に依存します。
  • 🤖 AI 支援: GitHub CopilotなどのAIアシスタントは、コメントからパッケージ仕様、本体、オーバーロードされたサブルーチンを作成します。

Oracle PL/SQLパッケージの仕様と本体構造の概要

パッケージインとは何ですか Oracle?

Oracle PL / SQLの パッケージは論理的なグループですping 関連する サブプログラム (プロシージャ/関数)を単一の要素にまとめます。パッケージはコンパイルされ、後で再利用できるデータベースオブジェクトとして保存されます。

パッケージのコンポーネント

PL/SQLパッケージは2つの構成要素から成り立っています。

  • パッケージ仕様
  • パッケージ本体

パッケージ仕様

パッケージ仕様は、すべての公開宣言から構成されます。 variables, カーソルオブジェクト、プロシージャ、関数、および 例外.

以下に、パッケージ仕様のいくつかの特徴を示します。

  • 仕様書で宣言された要素は、パッケージの外部からアクセスできます。このような要素はパブリック要素と呼ばれます。
  • パッケージ仕様は独立した要素であり、パッケージ本体がなくても単独で存在できることを意味します。
  • パッケージが参照されるたびに、そのセッション専用のパッケージのインスタンスが作成されます。
  • セッションのインスタンスが作成された後、そのインスタンスで開始されたすべてのパッケージ要素は、セッションが終了するまで有効です。

構文

CREATE [OR REPLACE] PACKAGE <package_name> 
IS
<sub_program and public element declaration>
.
.
END <package name>

上記の構文は、パッケージ仕様の作成方法を示しています。

パッケージ本体

パッケージ本体は、パッケージ仕様に存在するすべての要素の定義で構成されます。また、仕様で宣言されていない要素の定義を含めることもできます。これらの要素はプライベート要素と呼ばれ、パッケージ内部からのみ呼び出すことができます。

以下に、パッケージ本体の特性を示します。

  • 仕様書で宣言されているすべてのサブルーチン/カーソルの定義が含まれている必要があります。
  • また、仕様書に明記されていないサブルーチンやその他の要素を含めることもできます。これらはプライベート要素と呼ばれます。
  • これは依存オブジェクトであり、パッケージ仕様に依存します。
  • 仕様がコンパイルされるたびに、パッケージ本体の状態は「無効」になります。そのため、仕様のコンパイル後には毎回再コンパイルする必要があります。
  • プライベート要素は、パッケージ本体で使用する前に最初に定義する必要があります。
  • パッケージ本体の最初の部分は、グローバル宣言部分です。これには、パッケージ全体から参照可能な変数、カーソル、およびプライベート要素(前方宣言)が含まれます。
  • パッケージの最後の部分は、パッケージの初期化部分であり、セッション内でパッケージが初めて参照されるたびに一度だけ実行されます。

構文:

CREATE [OR REPLACE] PACKAGE BODY <package_name>
IS
<global_declaration part>
<Private element definition>
<sub_program and public element definition>
.
<Package Initialization> 
END <package_name>

上記の構文は、パッケージ本体の作成方法を示しています。

次に、プログラム内でパッケージ要素を参照する方法を見ていきましょう。

パッケージ要素の参照

パッケージ内で要素が宣言および定義されたら、それらを使用するには要素を参照する必要があります。

パッケージのすべてのパブリック要素は、パッケージ名の後にピリオドで区切られた要素名を続けて呼び出すことで参照できます。 。 '。

パッケージのパブリック変数も同様に、値を割り当てたり、値を取得したりするために使用できます。 。 '。

PL/SQLでパッケージを作成する

PL/SQLでは、セッション内でパッケージが参照または呼び出されるたびに、そのパッケージの新しいインスタンスが作成されます。

Oracle 「パッケージの初期化」を通じて、このインスタンスの作成時にパッケージ要素を初期化したり、任意のアクティビティを実行したりする機能を提供します。

これは、パッケージのすべての要素を定義した後、パッケージ本体に記述される実行ブロックです。このブロックは、セッション内でパッケージが初めて参照されるたびに実行されます。

以下のスクリーンショットは、パッケージを作成する際に、パッケージ初期化ブロックがパッケージ本体内にどのように配置されるかを示しています。

パッケージ本体にパッケージ初期化ブロックを含むPL/SQLパッケージを作成する

構文

CREATE [OR REPLACE] PACKAGE BODY <package_name>
IS
<Private element definition>
<sub_program and public element definition>
.
BEGIN
<Package Initialization> 
END <package_name>

上記の構文は、パッケージ本体でのパッケージ初期化の定義を示しています。

事前申告

パッケージ内での前方宣言または前方参照とは、プライベート要素を個別に宣言し、パッケージ本体の後半部分でそれらを定義することに他なりません。

プライベート要素は、パッケージ本体内で既に宣言されている場合にのみ参照できます。そのため、前方宣言が使用されます。しかし、プライベート要素はほとんどの場合パッケージ本体の最初の部分で宣言および定義されているため、前方宣言の使用はあまり一般的ではありません。

前方宣言は、によって提供されるオプションです。 Oracle必須ではありません。使用するかどうかはプログラマーの要件によります。

以下のスクリーンショットは、プライベート要素がパッケージ本体内でどのように前方宣言され、その後定義されるかを示しています。

プライベート要素の前方宣言 Oracle PL/SQLパッケージ本体

構文:

CREATE [OR REPLACE] PACKAGE BODY <package_name>
IS
<Private element declaration>
.
.
.
<Public element definition that refer the above private element>
.
.
<Private element definition> 
.
BEGIN
<package_initialization code>; 
END <package_name>

上記の構文は前方宣言を示しています。プライベート要素はパッケージの前方部分で個別に宣言され、後半部分で定義されています。

パッケージ内でのカーソルの使用法

他の要素とは異なり、パッケージ内でカーソルを使用する際には注意が必要です。

カーソルがパッケージ仕様またはパッケージ本体のグローバル部分で定義されている場合、一度開かれたカーソルはセッション終了まで保持されます。

したがって、カーソルを参照する前に、必ずカーソル属性「%ISOPEN」を使用してカーソルの状態を確認する必要があります。

過負荷

オーバーロードとは、同じ名前を持つ複数のサブルーチンを作成する概念です。これらのサブルーチンは、引数の数、引数の型、または戻り値の型によって互いに異なります。つまり、同じ名前であっても、引数の数、引数の型、または戻り値の型が異なるサブルーチンは、オーバーロードとみなされます。

これは、複数のサブルーチンが同じタスクを実行する必要があるものの、それぞれの呼び出し方法を異なるものにしたい場合に便利です。この場合、サブルーチン名はすべて同じままで、呼び出し文に応じてパラメータが変更されます。

例1: この例では、「emp」テーブル内の従業員情報の値を取得および設定するためのパッケージを作成します。get_record関数は、指定された従業員番号に対応するレコードタイプの出力を返し、set_recordプロシージャは、そのレコードタイプのレコードをempテーブルに挿入します。

ステップ1)パッケージ仕様の作成

以下のスクリーンショットは、guru99_get_set パッケージ仕様が作成されている様子を示しています。 Oracle.

set_record と get_record を使用して guru99_get_set パッケージ仕様を作成します Oracle

CREATE OR REPLACE PACKAGE guru99_get_set
IS
PROCEDURE set_record (p_emp_rec IN emp%ROWTYPE);
FUNCTION get_record (p_emp_no IN NUMBER) RETURN emp%ROWTYPE;
END guru99_get_set;
/

出力:

Package created

Code 説明

  • Code 1行目~5行目: guru99_get_set のパッケージ仕様を、1つのプロシージャと1つの関数で作成します。これらは、このパッケージの公開要素となります。

ステップ2) パッケージにはパッケージ本体が含まれており、そこにすべてのプロシージャと関数の実際の定義が記述されています。このステップでは、パッケージ本体を作成します。

以下のスクリーンショットは、guru99_get_set パッケージ本体の定義を示しています。 Oracle.

set_record、get_record、および初期化ブロックを使用してguru99_get_setパッケージ本体を定義します。

CREATE OR REPLACE PACKAGE BODY guru99_get_set
IS
PROCEDURE set_record(p_emp_rec IN emp%ROWTYPE)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO emp
VALUES(p_emp_rec.emp_name,p_emp_rec.emp_no, p_emp_rec.salary,p_emp_rec.manager);
COMMIT;
END set_record;
FUNCTION get_record(p_emp_no IN NUMBER)
RETURN emp%ROWTYPE
IS
l_emp_rec emp%ROWTYPE;
BEGIN
SELECT * INTO l_emp_rec FROM emp where emp_no=p_emp_no;
RETURN l_emp_rec;
END get_record;
BEGIN
dbms_output.put_line('Control is now executing the package initialization part');
END guru99_get_set;
/

出力:

Package body created

Code 説明

  • Code 7行目: パッケージ本体を作成しています。
  • Code 9行目~16行目: 仕様書で宣言されている要素「set_record」を定義します。これは、PL/SQLでスタンドアロンプ​​ロシージャを定義するのと同じです。
  • Code 17行目~24行目: 要素「get_record」を定義します。これは、独立した関数を定義するのと同じです。
  • Code 25行目~26行目: パッケージの初期化部分を定義します。

ステップ3) 上記で作成したパッケージを参照して、レコードを挿入および表示するための匿名ブロックを作成します。

以下のスクリーンショットは、パッケージを呼び出す匿名ブロックと、その出力を示しています。 Oracle.

guru99_get_set を呼び出す匿名ブロックが、従業員レコードを挿入して出力を表示します。

DECLARE
l_emp_rec emp%ROWTYPE;
l_get_rec emp%ROWTYPE;
BEGIN
dbms_output.put_line('Insert new record for employee 1004');
l_emp_rec.emp_no:=1004;
l_emp_rec.emp_name:='CCC';
l_emp_rec.salary:=20000;
l_emp_rec.manager:='BBB';
guru99_get_set.set_record(l_emp_rec);
dbms_output.put_line('Record inserted');
dbms_output.put_line('Calling get function to display the inserted record');
l_get_rec:=guru99_get_set.get_record(1004);
dbms_output.put_line('Employee name: '||l_get_rec.emp_name);
dbms_output.put_line('Employee number:'||l_get_rec.emp_no);
dbms_output.put_line('Employee salary:'||l_get_rec.salary);
dbms_output.put_line('Employee manager:'||l_get_rec.manager);
END;
/

出力:

Insert new record for employee 1004
Control is now executing the package initialization part
Record inserted
Calling get function to display the inserted record
Employee name: CCC
Employee number: 1004
Employee salary: 20000
Employee manager: BBB

Code 説明:

  • Code 34行目~37行目: パッケージの「set_record」要素を呼び出すために、匿名ブロック内でレコードタイプ変数のデータを設定します。
  • Code 38行目: guru99_get_set パッケージの 'set_record' が呼び出されました。これでパッケージがインスタンス化され、セッション終了まで保持されます。これはパッケージへの最初の呼び出しであるため、パッケージの初期化部分が実行され、'set_record' 要素によってレコードがテーブルに挿入されます。
  • Code 41行目: 挿入された従業員の詳細を表示するために、「get_record」要素を呼び出します。この呼び出し中にパッケージが2回目に参照されますが、パッケージはこのセッションで既に初期化されているため、初期化部分は再度実行されません。
  • Code 42行目~45行目: 従業員の詳細を印刷します。

パッケージ内の依存関係

パッケージは論理グループであるためping 関連する事柄には、いくつかの依存関係があります。以下に、対処すべき依存関係を示します。

  • 仕様書は独立したオブジェクトである。
  • パッケージ本体は仕様に依存します。
  • パッケージ本体は個別にコンパイルできます。仕様がコンパイルされるたびに、パッケージ本体も再コンパイルする必要があります。そうしないと、パッケージ本体は無効になってしまうからです。
  • パッケージ本体内のサブルーチンで、プライベート要素に依存するものは、プライベート要素の宣言後にのみ定義されるべきである。
  • 仕様書および本文中で参照されるデータベースオブジェクトは、パッケージコンパイル時に有効な状態である必要があります。

パッケージ情報

パッケージが作成されると、パッケージソース、サブルーチンの詳細、オーバーロードの詳細などのパッケージ情報が利用可能になります。 Oracle データ辞書テーブル。

以下の表は、データ辞書テーブルと、各テーブルで使用可能なパッケージ情報を示しています。

テーブル名 詳細説明 クエリー
すべてのオブジェクト パッケージの詳細情報(オブジェクトID、作成日、最終DDL時刻など)を提供します。すべてのユーザーによって作成されたオブジェクトが含まれています。 SELECT * FROM all_objects where object_name =' '
ユーザーオブジェクト パッケージの詳細情報(オブジェクトID、作成日、最終DDL時刻など)を提供します。現在のユーザーによって作成されたオブジェクトが含まれています。 SELECT * FROM user_objects where object_name =' '
ALL_SOURCE すべてのユーザーが作成したオブジェクトのソースを提供します。 SELECT * FROM all_source where name=' '
USER_SOURCE 現在のユーザーが作成したオブジェクトのソースを示します。 SELECT * FROM user_source where name=' '
すべての手順 すべてのユーザーによって作成されたサブルーチンのオブジェクトID、オーバーロードの詳細などを表示します。 SELECT * FROM all_procedures Where object_name=' '
USER_PROCEDURES 現在のユーザーによって作成されたサブプログラムの詳細 (object_id、オーバーロードの詳細など) を示します。 SELECT * FROM user_procedures Where object_name=' '

UTL_FILE – 概要

UTL_FILEは、 Oracle 特殊なタスクを実行するために使用されます。主にPL/SQLパッケージまたはサブプログラムからオペレーティングシステムファイルを読み書きするために使用されます。ファイルへの情報入力とファイルからの情報取得のための独立した機能を備えています。また、ネイティブ文字セットでの読み書きも可能です。

プログラマーはこれを利用してあらゆる種類のオペレーティングシステムファイルを書き込むことができ、ファイルはデータベースサーバーに直接書き込まれます。書き込み時にファイル名とディレクトリパスが指定されます。

よくあるご質問

パッケージは、モジュール性、情報隠蔽、およびアプリケーション設計の容易化を実現します。仕様は公開インターフェースを提供し、本体は実装を隠蔽します。 Oracle 最初の呼び出し時にパッケージをメモリにロードするため、後続のサブルーチン呼び出しではディスクI/Oが回避され、実行速度が向上します。

パッケージは多くの関連するグループをまとめます サブプログラム また、共有オブジェクトは単一の名前で管理され、公開仕様と非公開の本体が分離されます。スタンドアロンのプロシージャまたは関数は、インターフェースと実装が分離されていない、単一の独立したスキーマオブジェクトです。

はい、仕様書が変数、定数、型、または例外のみを宣言している場合は必要です。仕様書が手続き、関数、またはカーソルを宣言すると、それらの実装を記述する必要があるため、本体が必須となります。それ以外の場合は、仕様書は単独で成立します。

仕様と本文の両方を削除するには DROP PACKAGE を、本文のみを削除するには DROP PACKAGE BODY を使用します。無効なパッケージを再コンパイルするには ALTER PACKAGE package_name COMPILE を使用するか、変更後に本文のみを再構築するには COMPILE BODY を使用します。

%ROWTYPE属性は、 記録 そのフィールドはempテーブルの列と一致します。emp%ROWTYPEを使用することで、get_recordおよびset_recordパラメータがテーブル構造と整合するため、列の変更に伴うコード編集が少なくて済みます。

はい。パッケージを参照する各セッションは、独自のインスタンス化とパッケージ状態を取得し、そのセッションの存続期間中はそれが維持されます。本体を再コンパイルすると、その状態は破棄され、次回の呼び出し時にORA-04068エラーが発生します。

Yes. GitHubコパイロット コメントからパッケージ仕様、対応する本体、オーバーロードされたサブルーチンを作成し、%ROWTYPE パラメータを提案します。 Revデプロイする前に、生成された境界、初期化ブロック、および例外処理を確認してください。

AIアシスタントは、パッケージをスキャンして、無効な状態、欠落した本体定義、仕様変更時に壊れる依存関係チェーンを検出します。この機械学習によるレビューにより、パッケージが本番環境に移行する前に、曖昧なオーバーロードされたサブルーチンや再コンパイルのリスクが警告されます。