136 DBMS_PIPE
DBMS_PIPE
パッケージによって、同じインスタンスにある複数のセッションの通信を行います。Oracleパイプは、UNIXで使用するパイプと概念は似ていますが、オペレーティング・システムのパイプ・メカニズムを使用して実装されていません。
136.1 DBMS_PIPEの概要
パイプ機能には、複数の潜在的なアプリケーション(外部サービス・インタフェース、独立したトランザクション、アラート(トランザクション以外)、デバッグおよびコンセントレータ)があります。
-
外部サービス・インタフェース: RDBMS外部にあるユーザー記述のサービスと通信できます。これは、共有サーバー・プロセスで効果的に行うことができるため、サービスの複数インスタンスが同時に実行されます。さらに、サービスは非同期で使用できます。サービスのリクエスタは、待機応答をブロックする必要がありません。リクエスタは、(タイムアウトに関係なく)後でチェックできます。このサービスは、Oracleがサポートする任意の3GL言語で記述できます。
-
独立したトランザクション: パイプは、独立したトランザクション(トリガーで検出されたセキュリティ違反のロギングなど)内で操作を実行できる別のセッションと通信できます。
-
アラート(トランザクション以外): ポーリングするための待機プロセスを要求せずに、別のプロセスを転送できます。アプリケーションにアラートを通知するAFTER行またはAFTER文トリガーがある場合、アプリケーションは、このアラートをデータが変更された可能性を示すためのアラートとして処理します。アプリケーションはそのデータを読み込み、現行の値を取得します。これはAFTERトリガーなので、アプリケーションは、
SELECT
FOR
UPDATE
を行って正しいデータを読み込んだことを確認しようとします。 -
デバッグ: トリガーおよびストアド・プロシージャは、デバッグ情報をパイプに送信できます。別のセッションは、パイプからの読込みを続行し、その内容をスクリーンに表示したりファイルに書き込むことができます。
-
コンセントレータ: これは、少数のネットワーク接続に対して多数のユーザーがいる場合のユーザーの多重化や、複数のユーザー・トランザクションを1つのDBMSトランザクションに集中化する場合のパフォーマンス改善に役立ちます。
136.2 DBMS_PIPEのセキュリティ・モデル
DBMS_PIPE
とそのサブプログラムを使用するには、そのパッケージに対するEXECUTE
権限が必要になります。セキュリティは、CREATE_PIPE
ファンクションのprivate
パラメータを使用してパイプを作成し、特定のユーザーやロールに特定の機能やパイプ名のみを公開する共通パッケージを記述することで強固なものになります。
セキュリティ要件に応じて、パブリック・パイプまたはプライベート・パイプのいずれかを選択できます(「DBMS_PIPEの操作上のノート」を参照)。
DBMS_PIPE
パッケージは、実行者の権限を使用します。つまり、メッセージの送受信操作は実行者のスキーマで実行されることになります。
クラウド・オブジェクト・ストアでDBMS_PIPE
メッセージを使用するには、DBMS_PIPE
パッケージ、DBMS_CLOUD
パッケージおよび資格証明オブジェクト(オブジェクト・ストアURIにアクセスするため)に対するEXECUTE
権限が必要になります。
参照:
-
そのパッケージの詳細とクラウド・サービス資格証明の操作の詳細は、「DBMS_CLOUD」を参照してください
136.4 DBMS_PIPEの操作上のノート
Oracleパイプを介して送信する情報は、システム・グローバル領域(SGA)にバッファリングされます。パイプ内のすべての情報は、インスタンスがシャットダウンすると失われます。
警告:
パイプはトランザクションから独立しています。トランザクション制御に影響を与える可能性がある場合は、注意してパイプを使用してください。
オプションとして、永続メッセージ・ストレージにはクラウド・オブジェクト・ストアを使用できます。パイプからのメッセージを送受信するためのプロセスは、ローカル・ストレージとクラウド・ストレージのどちらを使用しても大きな違いはありませんが、クラウド・ストレージ、資格証明オブジェクトおよび関連するクラウドURIを指定する必要がある点で異なります。DBMS_PIPE
は、オブジェクト・ストレージとの統合にDBMS_CLOUD
パッケージを使用します。つまり、DBMS_PIPE
は、DBMS_CLOUD
で許容されるすべてのオブジェクト・ストアと資格証明タイプをサポートしていることになります。
オブジェクト・ストレージにパイプ・メッセージを格納すると、同じリージョンまたは異なるリージョンの2つ以上のデータベースがDBMS_PIPE
メッセージを使用して通信できるようになり、パイプに格納できるメッセージの最大数の制限がなくなります。つまり、あるReal Application Cluster (RAC)インスタンスでオープンしているデータベース・インスタンスは、異なるクラスタ・インスタンスで実行しているプロセス間の通信にDBMS_PIPE
を確実に使用できるということです。
ロック・メカニズムは、クラウド・オブジェクト・ストア内で一度に1つの送信操作または受信操作のみが動作可能になるように実装されています。ロック・ファイルはプロセスがクラウド・ストアの使用を開始したときに作成され、操作が完了すると削除されます。ロックが存在していない場合にのみ、プロセスはクラウド・ストアの操作を開始できます。プロセスは、指定された最大待機時間に達するまで再試行します。すでに動作していない不明なプロセスによってロックが残された場合、そのロックは削除され、現在のプロセスが15分後にクラウド・ストアへのアクセスを試行すると再作成されます。
ノート:
クラウド・オブジェクト・ストアを使用して異なるデータベース間でDBMS_PIPE
にアクセスする場合は、プライベート・パイプまたはパブリック・パイプに必要なアクセス権限付きでパイプが作成されるように、メッセージの送受信前にCREATE_PIPE
関数を使用することをお薦めします。
参照:
-
サポートされているURI形式については、Oracle Autonomous Database Serverlessの使用を参照してください
-
DBMS_CLOUD
サブプログラムとREST APIについては、Oracle Autonomous Database Serverlessの使用を参照してください -
サポートされている資格証明タイプの詳細は、Oracle Autonomous Database Serverlessの使用を参照してください
DBMS_PIPE
の操作は、次のトピックに関して行われます。
-
パブリック・パイプ
-
パイプへの書込みおよび読込み
-
プライベート・パイプ
-
シングルトン・パイプ
パブリック・パイプ
パブリック・パイプは、暗黙的または明示的に作成できます。暗黙的なパブリック・パイプの場合、パイプは最初の参照時に自動的に作成され、データがなくなると消去されます。パイプ記述子はSGAに格納されるため、空のパイプがキャッシュから削除されるまで、スペースを使用するオーバーヘッドが若干あります。
private
フラグをFALSE
に設定し、CREATE_PIPE
ファンクションをコールして、明示的なパブリック・パイプを作成します。明示的に作成したパイプは、REMOVE_PIPE
ファンクションをコールして割当て解除する必要があります。
パブリック・パイプのドメインは、明示的または暗黙的にパイプが作成されたスキーマです。
パイプの読取りおよび書込み
各パブリック・パイプは非同期に動作します。スキーマ・ユーザーがDBMS_PIPE
パッケージに対するEXECUTE
許可を持ち、パブリック・パイプ名を知っている場合にかぎり、任意の数のスキーマ・ユーザーがパブリック・パイプへの書込みを行うことができます。ただし、バッファに入っている情報を1人のユーザーが読み込むと、その情報はバッファから消去されるため、同じパイプの他のユーザーは読み込むことができません。
送信側セッションでは、PACK_MESSAGE
プロシージャに1つ以上コールを行ってメッセージを作成します。このプロシージャは、セッションのローカル・メッセージ・バッファにメッセージを追加します。このバッファ内の情報は、メッセージ送信に使用するパイプ名を指定したSEND_MESSAGE
ファンクションをコールして送信されます。SEND_MESSAGE
をコールすると、ローカル・バッファにスタックされたすべてのメッセージが送信されます。
メッセージを受信するプロセスは、メッセージを受信するパイプ名を指定したRECEIVE_MESSAGE
ファンクションをコールします。次に、UNPACK_MESSAGE
プロシージャをコールして、メッセージ内の各項目にアクセスします。
プライベート・パイプ
CREATE_PIPE
ファンクションをコールして、プライベート・パイプを明示的に作成します。プライベート・パイプは、一度作成されると、REMOVE_PIPE
ファンクションをコールして明示的に割当て解除するまで共有メモリーに存続します。プライベート・パイプは、データベース・インスタンスがシャットダウンしたときにも割当て解除されます。
メモリーに暗黙的なパイプが存在し、そのパイプと作成しようとするプライベート・パイプが同じ名前の場合、プライベート・パイプは作成できません。この場合は、CREATE_PIPE
からエラーが戻されます。
プライベート・パイプへのアクセスは、次のように限定されます。
-
パイプ作成者と同じユーザーIDで実行中のセッション
-
パイプ作成者と同じユーザーID権限ドメインで実行中のストアド・サブプログラム
-
SYSDBA
として接続したユーザー
これ以外のユーザーがパイプ上のメッセージの送受信やパイプの削除を試みると、即時にエラーが発生します。別のユーザーが同じ名前のパイプを作成しようとしても、エラーが発生します。
パブリック・パイプと同様に、SEND_MESSAGE
をコールする前にPACK_MESSAGE
へのコールを使用して、最初にメッセージを作成する必要があります。同様に、RECEIVE_MESSAGE
をコールしてメッセージを取り出してから、UNPACK_MESSAGE
をコールしてメッセージ内の項目にアクセスする必要があります。
シングルトン・パイプ
シングルトン・パイプは、現在のデータベース・インスタンスの共有メモリーに単一のメッセージをキャッシュする機能を提供し、データベース・セッション間のメッセージの高スループット同時読取りが可能になります。RACデータベースでは、パイプはデータベース・インスタンス間で同期されません。それぞれのデータベース・インスタンスには独自のパイプがあり、データベース・インスタンスのメモリーに対してプライベートです。
シングルトン・パイプには、単一のメッセージをキャッシュできます。このパイプは、メッセージの合計サイズ32,767バイトまでの複数のフィールドで構成できます。DBMS_PIPE
は、PACK_MESSAGE
プロシージャを使用することで、メッセージ内に複数の属性をパックする機能をサポートしています。
シングルトン・パイプは、パブリックまたはプライベートにすることも、暗黙的または明示的にすることもできます。プライベート・シングルトン・パイプを使用すると、メッセージはパイプの作成者と同じユーザーのセッションのみが受信できるようになります。パブリック・シングルトン・パイプ内のメッセージは、DBMS_PIPE
パッケージに対するEXECUTE
権限がある任意のデータベース・セッションで受信できます。
シングルトン・パイプは、無効化されるかパージされるまでパイプにメッセージをキャッシュします。パイプのパージによる明示的な無効化は、PURGE
プロシージャを使用するか、SEND_MESSAGE
ファンクションを使用したメッセージの上書きによって実施します。自動的な無効化は、CREATE_PIPE
ファンクションとSEND_MESSAGE
ファンクションの一部として指定されたshelflife時間が経過すると発生します。
ユーザー定義のキャッシュ・ファンクションは、シングルトン・パイプにメッセージを自動的に移入するために使用できます。これは、RECEIVE_MESSAGE
ファンクションを使用してメッセージを読み取るときに指定できます。キャッシュ内にメッセージがない場合やメッセージのshelflife時間が経過していた場合は、シングルトン・パイプによって新しいメッセージがパイプに自動的に移入されます。キャッシュ・ファンクションは、空のパイプからメッセージを受信できなかったときの条件ロジックを回避することで、パイプの使用を簡素化します。また、シングルトン・パイプからのメッセージの読取り時にキャッシュ・ミスがなくなります。
ノート:
RECEIVE_MESSAGE
にキャッシュ・ファンクションを使用する場合、そのキャッシュ・ファンクションの実行にかかった時間は、メッセージの受信に指定された全体的なタイムアウトには含まれません。
シングルトン・パイプは、Oracle Databaseのメモリーから削除されないため、最大のキャッシュ・ヒットが保証されます。明示的なシングルトン・パイプは、REMOVE_PIPE
プロシージャを使用して削除するか、データベースの再起動まで、データベース・メモリーに存在します。暗黙的なシングルトン・パイプは、パイプにキャッシュされたメッセージが1つになるまでデータベース・メモリーに存在します。
136.5 DBMS_PIPEの例外
DBMS_PIPE
パッケージ・サブプログラムは、次の表に示すエラーを戻すことができます。
表136-1 DBMS_PIPEのエラー
エラー | 説明 |
---|---|
|
パイプ名はNULLにできません。このエラーは、 |
|
パイプへのアクセス権限が不十分です。このエラーは、パラメータ・リストにあるプライベート・パイプを参照するサブプログラムによって戻されます。 |
136.6 DBMS_PIPEの例
次の例は、PL/SQLのデバッグ、Pro*Cのデバッグ、システム・コマンドの実行、および外部サービス・インタフェースでのDBMS_PIPEの使用例を示します。
例1: デバッグ - PL/SQL
この例は、デバッグ情報をパイプに設定するために、PL/SQLプログラムがコールできるプロシージャを示しています。
CREATE OR REPLACE PROCEDURE debug (msg VARCHAR2) AS status NUMBER; BEGIN DBMS_PIPE.PACK_MESSAGE(LENGTH(msg)); DBMS_PIPE.PACK_MESSAGE(msg); status := DBMS_PIPE.SEND_MESSAGE('plsql_debug'); IF status != 0 THEN raise_application_error(-20099, 'Debug error'); END IF; END debug;
例2: デバッグ - Pro*C
次のPro*Cコードでは、前述の例のPLSQL_DEBUG
パイプから受信したメッセージが表示されます。Pro*Cセッションが別のウィンドウで実行されている場合、このセッションは、別のセッションで実行中のPL/SQLプログラムからデバッグ・プロシージャに送信されるメッセージの表示に使用できます。
#include <stdio.h>
#include <string.h>
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR username[20];
int status;
int msg_length;
char retval[2000];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE SQLCA;
void sql_error();
main()
{
-- Prepare username:
strcpy(username.arr, "HR/<password>");
username.len = strlen(username.arr);
EXEC SQL WHENEVER SQLERROR DO sql_error();
EXEC SQL CONNECT :username;
printf("connected\n");
-- Start an endless loop to look for and print messages on the pipe:
FOR (;;)
{
EXEC SQL EXECUTE
DECLARE
len INTEGER;
typ INTEGER;
sta INTEGER;
chr VARCHAR2(2000);
BEGIN
chr := '';
sta := dbms_pipe.receive_message('plsql_debug');
IF sta = 0 THEN
DBMS_PIPE.UNPACK_MESSAGE(len);
DBMS_PIPE.UNPACK_MESSAGE(chr);
END IF;
:status := sta;
:retval := chr;
IF len IS NOT NULL THEN
:msg_length := len;
ELSE
:msg_length := 2000;
END IF;
END;
END-EXEC;
IF (status == 0)
printf("\n%.*s\n", msg_length, retval);
ELSE
printf("abnormal status, value is %d\n", status);
}
}
void sql_error()
{
char msg[1024];
int rlen, len;
len = sizeof(msg);
sqlglm(msg, &len, &rlen);
printf("ORACLE ERROR\n");
printf("%.*s\n", rlen, msg);
exit(1);
}
例3: システム・コマンドの実行
この例は、PL/SQLとPro*Cコードによって、PL/SQLストアド・プロシージャ(または無名ブロック)がPL/SQLプロシージャをコールし、コマンドをリスニングしているPro*Cプログラムにパイプを介してそのコマンドを送信する処理を示します。
Pro*Cプログラムはスリープして、名前付きパイプにメッセージが着信するのを待ちます。メッセージが着信すると、Pro*Cプログラムはこれを処理し、system()コールを使用したUNIXコマンドの実行、埋込みSQLを使用したSQLコマンドの実行など、必要なアクションを行います。
DAEMON.SQL
は、PL/SQLパッケージ用のソース・コードです。このパッケージには、DBMS_PIPE
パッケージを使用してPro*Cデーモンに対してメッセージを送受信するプロシージャが含まれています。完全なハンドシェイクが使用されていることに注意してください。このデーモンは、常にメッセージをパッケージに返信します(STOP
コマンドの場合は除きます)。これによって、PL/SQLプロシージャはPro*Cデーモンが動作していることを確認できるため、デーモンのこの機能は重要です。
SQL*PlusまたはEnterprise Managerを使用して、無名PL/SQLブロックからDAEMONパッケージ・プロシージャをコールできます。たとえば:
SQLPLUS> variable rv number SQLPLUS> execute :rv := DAEMON.EXECUTE_SYSTEM('ls -la');
これにより、UNIXシステムでは、Pro*Cデーモンによってコマンドsystem("ls -la")が実行されます。
最初にデーモンを実行する必要があることに留意してください。デーモンは、バックグラウンドで実行したり、デーモンをコールしたSQL*PlusまたはEnterprise Managerセッションの近くにある別のウィンドウで実行できます。
また、DAEMON
.SQL
は、DBMS_OUTPUT
パッケージを使用して結果を表示します。この例を動作させるには、このパッケージに対するEXECUTE権限が必要です。
DAEMON.SQLの例。次の例は、PL/SQL DAEMON
パッケージのコード例です。
CREATE OR REPLACE PACKAGE daemon AS FUNCTION execute_sql(command VARCHAR2, timeout NUMBER DEFAULT 10) RETURN NUMBER; FUNCTION execute_system(command VARCHAR2, timeout NUMBER DEFAULT 10) RETURN NUMBER; PROCEDURE stop(timeout NUMBER DEFAULT 10); END daemon; / CREATE OR REPLACE PACKAGE BODY daemon AS FUNCTION execute_system(command VARCHAR2, timeout NUMBER DEFAULT 10) RETURN NUMBER IS status NUMBER; result VARCHAR2(20); command_code NUMBER; pipe_name VARCHAR2(30); BEGIN pipe_name := DBMS_PIPE.UNIQUE_SESSION_NAME; DBMS_PIPE.PACK_MESSAGE('SYSTEM'); DBMS_PIPE.PACK_MESSAGE(pipe_name); DBMS_PIPE.PACK_MESSAGE(command); status := DBMS_PIPE.SEND_MESSAGE('daemon', timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR(-20010, 'Execute_system: Error while sending. Status = ' || status); END IF; status := DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR(-20011, 'Execute_system: Error while receiving. Status = ' || status); END IF; DBMS_PIPE.UNPACK_MESSAGE(result); IF result <> 'done' THEN RAISE_APPLICATION_ERROR(-20012, 'Execute_system: Done not received.'); END IF; DBMS_PIPE.UNPACK_MESSAGE(command_code); DBMS_OUTPUT.PUT_LINE('System command executed. result = ' || command_code); RETURN command_code; END execute_system; FUNCTION execute_sql(command VARCHAR2, timeout NUMBER DEFAULT 10) RETURN NUMBER IS status NUMBER; result VARCHAR2(20); command_code NUMBER; pipe_name VARCHAR2(30); BEGIN pipe_name := DBMS_PIPE.UNIQUE_SESSION_NAME; DBMS_PIPE.PACK_MESSAGE('SQL'); DBMS_PIPE.PACK_MESSAGE(pipe_name); DBMS_PIPE.PACK_MESSAGE(command); status := DBMS_PIPE.SEND_MESSAGE('daemon', timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR(-20020, 'Execute_sql: Error while sending. Status = ' || status); END IF; status := DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR(-20021, 'execute_sql: Error while receiving. Status = ' || status); END IF; DBMS_PIPE.UNPACK_MESSAGE(result); IF result <> 'done' THEN RAISE_APPLICATION_ERROR(-20022, 'execute_sql: done not received.'); END IF; DBMS_PIPE.UNPACK_MESSAGE(command_code); DBMS_OUTPUT.PUT_LINE ('SQL command executed. sqlcode = ' || command_code); RETURN command_code; END execute_sql; PROCEDURE stop(timeout NUMBER DEFAULT 10) IS status NUMBER; BEGIN DBMS_PIPE.PACK_MESSAGE('STOP'); status := DBMS_PIPE.SEND_MESSAGE('daemon', timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR(-20030, 'stop: error while sending. status = ' || status); END IF; END stop; END daemon;
DAEMON.PCの例。次の例は、Pro*Cデーモンのコード例です。バージョン1.5.x以降のPro*Cプリコンパイラを使用して、このコードをプリコンパイルする必要があります。この例には埋込みPL/SQLコードが含まれているため、USERID
およびSQLCHECK
オプションも指定する必要があります。
ノート:
PL/SQLブロックでVARCHAR
出力ホスト変数を使用するには、そのブロックの入力前に長さの要素を初期化する必要があります。
proc iname=daemon userid=HR/<password> sqlcheck=semantics
次に、通常の方法で、Cコンパイルしてリンクします。
#include <stdio.h>
#include <string.h>
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
char *uid = "HR/<password>";
int status;
VARCHAR command[20];
VARCHAR value[2000];
VARCHAR return_name[30];
EXEC SQL END DECLARE SECTION;
void
connect_error()
{
char msg_buffer[512];
int msg_length;
int buffer_size = 512;
EXEC SQL WHENEVER SQLERROR CONTINUE;
sqlglm(msg_buffer, &buffer_size, &msg_length);
printf("Daemon error while connecting:\n");
printf("%.*s\n", msg_length, msg_buffer);
printf("Daemon quitting.\n");
exit(1);
}
void
sql_error()
{
char msg_buffer[512];
int msg_length;
int buffer_size = 512;
EXEC SQL WHENEVER SQLERROR CONTINUE;
sqlglm(msg_buffer, &buffer_size, &msg_length);
printf("Daemon error while executing:\n");
printf("%.*s\n", msg_length, msg_buffer);
printf("Daemon continuing.\n");
}
main()
{
command.len = 20; /*initialize length components*/
value.len = 2000;
return_name.len = 30;
EXEC SQL WHENEVER SQLERROR DO connect_error();
EXEC SQL CONNECT :uid;
printf("Daemon connected.\n");
EXEC SQL WHENEVER SQLERROR DO sql_error();
printf("Daemon waiting...\n");
while (1) {
EXEC SQL EXECUTE
BEGIN
:status := DBMS_PIPE.RECEIVE_MESSAGE('daemon');
IF :status = 0 THEN
DBMS_PIPE.UNPACK_MESSAGE(:command);
END IF;
END;
END-EXEC;
IF (status == 0)
{
command.arr[command.len] = '\0';
IF (!strcmp((char *) command.arr, "STOP"))
{
printf("Daemon exiting.\n");
break;
}
ELSE IF (!strcmp((char *) command.arr, "SYSTEM"))
{
EXEC SQL EXECUTE
BEGIN
DBMS_PIPE.UNPACK_MESSAGE(:return_name);
DBMS_PIPE.UNPACK_MESSAGE(:value);
END;
END-EXEC;
value.arr[value.len] = '\0';
printf("Will execute system command '%s'\n", value.arr);
status = system(value.arr);
EXEC SQL EXECUTE
BEGIN
DBMS_PIPE.PACK_MESSAGE('done');
DBMS_PIPE.PACK_MESSAGE(:status);
:status := DBMS_PIPE.SEND_MESSAGE(:return_name);
END;
END-EXEC;
IF (status)
{
printf
("Daemon error while responding to system command.");
printf(" status: %d\n", status);
}
}
ELSE IF (!strcmp((char *) command.arr, "SQL")) {
EXEC SQL EXECUTE
BEGIN
DBMS_PIPE.UNPACK_MESSAGE(:return_name);
DBMS_PIPE.UNPACK_MESSAGE(:value);
END;
END-EXEC;
value.arr[value.len] = '\0';
printf("Will execute sql command '%s'\n", value.arr);
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL EXECUTE IMMEDIATE :value;
status = sqlca.sqlcode;
EXEC SQL WHENEVER SQLERROR DO sql_error();
EXEC SQL EXECUTE
BEGIN
DBMS_PIPE.PACK_MESSAGE('done');
DBMS_PIPE.PACK_MESSAGE(:status);
:status := DBMS_PIPE.SEND_MESSAGE(:return_name);
END;
END-EXEC;
IF (status)
{
printf("Daemon error while responding to sql command.");
printf(" status: %d\n", status);
}
}
ELSE
{
printf
("Daemon error: invalid command '%s' received.\n",
command.arr);
}
}
ELSE
{
printf("Daemon error while waiting for signal.");
printf(" status = %d\n", status);
}
}
EXEC SQL COMMIT WORK RELEASE;
exit(0);
例4: 外部サービス・インタフェース
ユーザー作成の3GLコードを、OCIまたはプリコンパイラ・プログラムに設定します。プログラムは、データベースに接続してPL/SQLコードを実行し、パイプから要求を読み込み、結果を計算してから、PL/SQLコードを実行して、パイプ上の結果をリクエスタに返信します。
次に、株式サービス要求の例を示します。すべてのサービス・リクエストについてパイプに渡す引数の推奨する順序を次に示します。
protocol_version VARCHAR2 - '1', 10 bytes or less returnpipe VARCHAR2 - 30 bytes or less service VARCHAR2 - 30 bytes or less arg1 VARCHAR2/NUMBER/DATE ... argn VARCHAR2/NUMBER/DATE
結果を戻すための推奨する書式を次に示します。
success VARCHAR2 - 'SUCCESS' if OK, otherwise error message arg1 VARCHAR2/NUMBER/DATE ... argn VARCHAR2/NUMBER/DATE
OCIまたはPRO*(疑似コードで)を使用して、株価要求サーバーを次のように設定します。
<loop forever> BEGIN dbms_stock_server.get_request(:stocksymbol); END; <figure out price based on stocksymbol (probably from some radio signal), set error if can't find such a stock> BEGIN dbms_stock_server.return_price(:error, :price); END;
クライアントは次のように設定します。
BEGIN :price := stock_request('YOURCOMPANY'); end;
前述の株価要求サーバーでコールしたストアド・プロシージャdbms_stock_server
は、次のように設定します。
CREATE OR REPLACE PACKAGE dbms_stock_server IS PROCEDURE get_request(symbol OUT VARCHAR2); PROCEDURE return_price(errormsg IN VARCHAR2, price IN VARCHAR2); END; CREATE OR REPLACE PACKAGE BODY dbms_stock_server IS returnpipe VARCHAR2(30); PROCEDURE returnerror(reason VARCHAR2) IS s INTEGER; BEGIN dbms_pipe.pack_message(reason); s := dbms_pipe.send_message(returnpipe); IF s <> 0 THEN raise_application_error(-20000, 'Error:' || to_char(s) || ' sending on pipe'); END IF; END; PROCEDURE get_request(symbol OUT VARCHAR2) IS protocol_version VARCHAR2(10); s INTEGER; service VARCHAR2(30); BEGIN s := dbms_pipe.receive_message('stock_service'); IF s <> 0 THEN raise_application_error(-20000, 'Error:' || to_char(s) || 'reading pipe'); END IF; dbms_pipe.unpack_message(protocol_version); IF protocol_version <> '1' THEN raise_application_error(-20000, 'Bad protocol: ' || protocol_version); END IF; dbms_pipe.unpack_message(returnpipe); dbms_pipe.unpack_message(service); IF service != 'getprice' THEN returnerror('Service ' || service || ' not supported'); END IF; dbms_pipe.unpack_message(symbol); END; PROCEDURE return_price(errormsg in VARCHAR2, price in VARCHAR2) IS s INTEGER; BEGIN IF errormsg is NULL THEN dbms_pipe.pack_message('SUCCESS'); dbms_pipe.pack_message(price); ELSE dbms_pipe.pack_message(errormsg); END IF; s := dbms_pipe.send_message(returnpipe); IF s <> 0 THEN raise_application_error(-20000, 'Error:'||to_char(s)|| ' sending on pipe'); END IF; END; END;
クライアントがコールするプロシージャは、次のように設定します。
CREATE OR REPLACE FUNCTION stock_request (symbol VARCHAR2) RETURN VARCHAR2 IS s INTEGER; price VARCHAR2(20); errormsg VARCHAR2(512); BEGIN dbms_pipe.pack_message('1'); -- protocol version dbms_pipe.pack_message(dbms_pipe.unique_session_name); -- return pipe dbms_pipe.pack_message('getprice'); dbms_pipe.pack_message(symbol); s := dbms_pipe.send_message('stock_service'); IF s <> 0 THEN raise_application_error(-20000, 'Error:'||to_char(s)|| ' sending on pipe'); END IF; s := dbms_pipe.receive_message(dbms_pipe.unique_session_name); IF s <> 0 THEN raise_application_error(-20000, 'Error:'||to_char(s)|| ' receiving on pipe'); END IF; dbms_pipe.unpack_message(errormsg); IF errormsg <> 'SUCCESS' THEN raise_application_error(-20000, errormsg); END IF; dbms_pipe.unpack_message(price); RETURN price; END;
一般的に、株式サービス・アプリケーション・サーバーに対してのみDBMS_STOCK_SERVICE
のGRANT
EXECUTE
を実行し、このサービスを利用できるユーザーに対してのみstock_request
のGRANT
EXECUTE
を実行します。
参照:
136.7 DBMS_PIPEサブプログラムの要約
この表は、DBMS_PIPE
サブプログラムを示し、簡単に説明しています。
表136-2 DBMS_PIPEパッケージのサブプログラム
サブプログラム | 説明 |
---|---|
パイプを作成します(プライベート・パイプの場合は必須です)。 |
|
グローバルに設定された |
|
グローバルに設定された |
|
バッファにある次の項目のデータ・タイプを戻します。 |
|
ローカル・バッファにメッセージを作成します。 |
|
名前付きパイプの内容をパージします。 |
|
名前付きパイプからローカル・バッファにメッセージをコピーします。 |
|
名前付きパイプを削除します。 |
|
ローカル・バッファの内容をパージします。 |
|
メッセージを名前付きパイプに送信します。名前付きパイプが存在しない場合は、パブリック・パイプが暗黙的に作成されます。 |
|
グローバル |
|
グローバル |
|
一意のセッション名を戻します。 |
|
バッファにある次の項目にアクセスします。 |
136.7.1 CREATE_PIPEファンクション
このファンクションは、パブリック・パイプまたはプライベート・パイプを明示的に作成します。private
フラグがTRUE
の場合、パイプ作成者がそのプライベート・パイプの所有者として割り当てられます。
明示的に作成されたパイプは、REMOVE_PIPE
をコールするか、またはインスタンスをシャットダウンすることによってのみ削除できます。
構文
DBMS_PIPE.CREATE_PIPE (
pipename IN VARCHAR2,
maxpipesize IN INTEGER DEFAULT 65536,
private IN BOOLEAN DEFAULT TRUE,
singleton IN BOOLEAN DEFAULT FALSE,
shelflife IN INTEGER DEFAULT 0)
RETURN INTEGER;
プラグマ
pragma restrict_references(create_pipe,WNDS,RNDS);
パラメータ
表136-3 CREATE_PIPEファンクションのパラメータ
パラメータ | 説明 |
---|---|
|
作成するパイプの名前。
注意: |
|
パイプの最大サイズ(バイト単位)。 パイプ上のすべてのメッセージの合計サイズは、この数を超えることはできません。この最大値を超えると、そのメッセージはブロックされます。デフォルトの パイプの |
|
デフォルトの パブリック・パイプは、 |
|
値
|
|
オプションで、シングルトン・パイプにキャッシュされるメッセージの有効期限を秒単位で設定するために使用します。 デフォルト値の0は、メッセージが期限切れにならないことを示します。 シングルトン・パイプのメッセージの |
戻り値
表136-4 CREATE_PIPEファンクションの戻り値
戻り値 | 説明 |
---|---|
|
成功。 パイプが存在し、パイプを作成するユーザーにそのパイプの使用が認可されている場合、Oracleは0(ゼロ)を戻して成功であることを示し、パイプ内のデータはそのまま残ります。
|
|
既存のパイプをシングルトン・パイプに変換できませんでした。 複数の既存のメッセージがある暗黙的パイプは、シングルトン・パイプに変換できません。 シングルトン・パイプではない明示的なパイプの場合、 |
|
|
|
命名競合のために失敗。 同じ名前のパイプが存在し、別のユーザーがそのパイプを作成した場合、Oracleではエラー |
例外
表136-5 CREATE_PIPEファンクションの例外
例外 | 説明 |
---|---|
|
アクセス権エラー: 同名のパイプが存在するため使用できません。 |
136.7.2 GET_CREDENTIAL_NAMEファンクション
このファンクションでは、デフォルトの資格証明としてクラウドで使用されるグローバルcredential_name
変数を取得します。
構文
DBMS_PIPE.GET_CREDENTIAL_NAME ()
RETURN VARCHAR2;
戻り値
このファンクションは、グローバルに設定されたcredential_name
変数を返します。この変数は、デフォルトでNULL
に設定されます。
136.7.3 GET_LOCATION_URIファンクション
このファンクションでは、デフォルトの場所URIとしてクラウドで使用されるグローバルlocation_uri
変数を取得します。
構文
DBMS_PIPE.GET_LOCATION_URI ()
RETURN VARCHAR2;
戻り値
このファンクションは、グローバルに設定されたlocation_uri
変数を返します。この変数は、デフォルトでNULL
に設定されます。
136.7.4 NEXT_ITEM_TYPEファンクション
このファンクションは、ローカル・メッセージ・バッファにある次の項目のタイプを判別します。
RECEIVE_MESSAGE
をコールして、ローカル・バッファにパイプ情報を設定した後、NEXT_ITEM_TYPE
をコールします。
構文
DBMS_PIPE.NEXT_ITEM_TYPE RETURN INTEGER;
プラグマ
pragma restrict_references(next_item_type,WNDS,RNDS);
戻り値
表136-6 NEXT_ITEM_TYPEファンクションの戻り値
戻り値 | 説明 |
---|---|
|
次の項目がありません。 |
|
|
|
|
|
|
|
|
|
|
136.7.5 PACK_MESSAGEプロシージャ
このプロシージャは、ユーザーのメッセージをローカル・メッセージ・バッファに作成します。
メッセージを送信するためには、最初にPACK_MESSAGE
を1回以上コールします。次に、SEND_MESSAGE
をコールして、ローカル・バッファにあるメッセージを名前付きパイプに送信します。
このプロシージャは、VARCHAR2
、NCHAR
、NUMBER
、DATE
、RAW
およびROWID
タイプの項目を受け入れるためにオーバーロードされます。バッファ内の各項目には、データ・バイトの他に、項目のタイプを示すための1バイト、および長さを格納するための2バイトが必要です。メッセージを終了するには、さらに1バイトが必要で、VARCHAR
以外のすべてのタイプのオーバーヘッドは4バイトです。
構文
DBMS_PIPE.PACK_MESSAGE ( item IN VARCHAR2); DBMS_PIPE.PACK_MESSAGE ( item IN NCHAR); DBMS_PIPE.PACK_MESSAGE ( item IN NUMBER); DBMS_PIPE.PACK_MESSAGE ( item IN DATE); DBMS_PIPE.PACK_MESSAGE_RAW ( item IN RAW); DBMS_PIPE.PACK_MESSAGE_ROWID ( item IN ROWID);
プラグマ
pragma restrict_references(pack_message,WNDS,RNDS); pragma restrict_references(pack_message_raw,WNDS,RNDS); pragma restrict_references(pack_message_rowid,WNDS,RNDS);
パラメータ
表136-7 PACK_MESSAGEプロシージャのパラメータ
パラメータ | 説明 |
---|---|
|
ローカル・メッセージ・バッファにパックする項目。 |
使用上のノート
Oracle Databaseのバージョン8.xでは、文字セットID(2バイト)および文字セット・フォーム(1バイト)が各データ項目に格納されています。そのため、Oracle Databaseのバージョン8.x使用時のオーバーヘッドは7バイトになります。
SEND_MESSAGE
をコールしてメッセージを送信するときは、メッセージを送信するパイプの名前を示す必要があります。パイプがすでに存在する場合は、そのパイプにアクセスするための十分な権限が必要です。パイプが存在しない場合は、自動的に作成されます。
例外
メッセージ・バッファ(現在は4096バイト)がオーバーフローした場合は、ORA-06558
が発生します。バッファ内の各項目には、実際のデータに加えて、タイプを示すために1バイト、長さを示すために2バイトが必要です。さらに、メッセージを終了するために1バイトが必要です。
136.7.6 PURGEプロシージャ
このプロシージャは、名前付きパイプの内容を空にします。
暗黙的に作成された空のパイプは、LRUアルゴリズムに従って、共有グローバル領域から削除されます。したがって、PURGE
をコールすると、暗黙的に作成したパイプに関連するメモリーを空にできます。
構文
DBMS_PIPE.PURGE ( pipename IN VARCHAR2);
プラグマ
pragma restrict_references(purge,WNDS,RNDS);
パラメータ
表136-8 PURGEプロシージャのパラメータ
パラメータ | 説明 |
---|---|
|
すべてのメッセージを削除するパイプの名前。 メッセージが廃棄されると、ローカル・バッファがそのメッセージで上書きされる場合があります。パイプ名は128バイト以下で指定し、大/小文字は区別されません。 |
使用上のノート
PURGE
プロシージャはRECEIVE_MESSAGE
をコールするため、メッセージがパイプからパージされるとき、ローカル・バッファはそのメッセージで上書きされる場合があります。また、不十分なアクセス権でパイプをパージしようとすると、ORA-23322
エラー(不十分な権限)を受け取ります。
例外
パイプを別のユーザーが所有している場合は、アクセス権エラーが発生します。
136.7.7 RECEIVE_MESSAGEファンクション
このファンクションは、メッセージをローカル・メッセージ・バッファにコピーします。
構文
DBMS_PIPE.RECEIVE_MESSAGE (
pipename IN VARCHAR2,
timeout IN INTEGER DEFAULT maxwait,
cache_func IN VARCHAR2 DEFAULT NULL)
RETURN INTEGER;
DBMS_PIPE.RECEIVE_MESSAGE (
pipename IN VARCHAR2,
timeout IN INTEGER DEFAULT maxwait,
credential_name IN VARCHAR2 DEFAULT NULL,
location_uri IN VARCHAR2 DEFAULT NULL)
RETURN INTEGER;
プラグマ
pragma restrict_references(receive_message,WNDS,RNDS);
パラメータ
表136-9 RECEIVE_MESSAGEファンクションのパラメータ
パラメータ | 説明 |
---|---|
|
メッセージを受信するパイプ名。
|
|
メッセージを待つ時間(秒単位)。 デフォルト値は定数 |
|
シングルトン・パイプに自動的にメッセージをキャッシュするために使用されるキャッシュ・ファンクション名で、PL/SQLファンクションまたはPL/SQLパッケージの埋込みファンクションとして作成できます。 指定した場合、そのキャッシュ・ファンクションは、 ファンクションの名前は、所有者スキーマで完全修飾されている必要があります:
キャッシュ・ファンクションの実行にかかった時間は、メッセージの受信に指定された全体的なタイムアウトには含まれません。 |
|
メッセージの格納に使用するクラウド・ストアの資格証明名。 デフォルト値は |
|
メッセージの格納に使用しているクラウド・ストアの場所URL。
資格証明名を指定する場合は、 |
戻り値
表136-10 RECEIVE_MESSAGEファンクションの戻り値
戻り値 | 説明 |
---|---|
|
成功。 |
|
タイムアウトしました。暗黙的に作成されたパイプが空の場合、そのパイプは削除されます。 |
|
パイプにあるレコードが、バッファに対して大きすぎます。(これは起りえないことです。) |
|
割込みが発生しました。 |
|
シングルトン以外のパイプにキャッシュ・ファンクションが指定されました。 |
|
パイプから読み込むための十分な権限がユーザーにありません。 |
使用上のノート
パイプからメッセージを受信するには、最初にRECEIVE_MESSAGE
をコールします。メッセージを受信すると、パイプからメッセージが削除されるため、メッセージは1回しか受信できません(シングルトン・パイプを使用していない場合)。暗黙的に作成されたパイプは、最後のレコードがそのパイプから削除された後で削除されます。暗黙的なシングルトン・パイプは、パイプにキャッシュされたメッセージが1つになるまでデータベース・メモリーに存在します。
RECEIVE_MESSAGE
のコール時に指定したパイプがすでに存在しない場合、Oracleはパイプを暗黙的に作成してメッセージの受信を待ちます。メッセージが指定したタイムアウト時間内に着信しなかった場合、そのコールは戻され、パイプは削除されます。
メッセージの受信後、1つ以上のUNPACK_MESSAGE
をコールして、メッセージ内の個別の項目にアクセスする必要があります。UNPACK_MESSAGE
プロシージャは、DATE
、NUMBER
、VARCHAR2
タイプの項目をアンパックするためにオーバーロードされ、さらに、RAW
およびROWID
項目をアンパックするための2つのプロシージャがあります。アンパックするデータのタイプが不明の場合は、NEXT_ITEM_TYPE
をコールして、バッファ内にある次の項目のタイプを判別します。
-
シングルトン・パイプが空
-
shelflife
時間が経過したため、シングルトン・パイプ内のメッセージが無効
キャッシュ・ファンクションは、空のパイプからメッセージを受信できなかったときの条件ロジックを回避することでシングルトン・パイプの使用を簡素化し、キャッシュ・ミスが発生しないようにします。
ノート:
データベース間メッセージングを実行する場合は、新しいデータベースで初めてのメッセージを受信する前に、CREATE_PIPE
ファンクションをコールする必要があります。このパイプの名前とそのプロパティは、別のデータベースでメッセージが送信されたパイプと同じになっている必要があります。
例外
表136-11 RECEIVE_MESSAGEファンクションの例外
例外 | 説明 |
---|---|
|
アクセス権エラー。パイプからレコードを削除するための権限が不十分です。パイプは別のユーザーが所有しています。 |
136.7.8 RESET_BUFFERプロシージャ
このプロシージャは、PACK_MESSAGE
およびUNPACK_MESSAGE
の位置設定インジケータを0(ゼロ)にリセットします。
すべてのパイプが1つのバッファを共有しているため、新規パイプを使用する前にバッファをリセットすると効果的です。これにより、初めてメッセージをパイプに送信するとき、バッファ内に残っていた期限切れのメッセージを誤って送信することがなくなります。
構文
DBMS_PIPE.RESET_BUFFER;
プラグマ
pragma restrict_references(reset_buffer,WNDS,RNDS);
136.7.9 REMOVE_PIPEファンクション
このファンクションは、明示的に作成されたパイプを削除します。
SEND_MESSAGE
で暗黙的に作成されたパイプは、空になると自動的に削除されます。ただし、CREATE_PIPE
で明示的に作成されたパイプは、REMOVE_PIPE
をコールするか、またはインスタンスをシャットダウンした場合にのみ削除されます。パイプ内の未使用のレコードは、パイプが削除される前にすべて削除されます。
これは、暗黙的に作成されたパイプでPURGE
をコールするのに似ています。
構文
DBMS_PIPE.REMOVE_PIPE ( pipename IN VARCHAR2) RETURN INTEGER;
プラグマ
pragma restrict_references(remove_pipe,WNDS,RNDS);
パラメータ
表136-12 REMOVE_PIPEファンクションのパラメータ
パラメータ | 説明 |
---|---|
|
削除するパイプ名。 |
戻り値
表136-13 REMOVE_PIPEファンクションの戻り値
戻り値 | 説明 |
---|---|
|
成功。 パイプが存在しない場合、またはパイプがすでに存在し、パイプを削除しようとするユーザーに削除が認可されている場合、Oracleは0(ゼロ)を戻して成功であることを示し、パイプ内に残っているデータが削除されます。 |
|
権限が不十分です。 パイプが存在しても、ユーザーにそのパイプへのアクセス権がない場合、Oracleはエラー |
例外
表136-14 REMOVE_PIPEファンクションの例外
例外 | 説明 |
---|---|
|
アクセス権エラー: パイプを削除する権限が不十分です。パイプは作成されていて、別のユーザーが所有しています。 |
136.7.10 SEND_MESSAGEファンクション
このファンクションは、メッセージを名前付きパイプに送信します。
PACK_MESSAGE
へのコールで入力されたメッセージは、ローカル・メッセージ・バッファに格納されます。CREATE_PIPE
を使用するとパイプを明示的に作成でき、それ以外の場合は暗黙的に作成されます。
構文
DBMS_PIPE.SEND_MESSAGE (
pipename IN VARCHAR2,
timeout IN INTEGER DEFAULT MAXWAIT,
maxpipesize IN INTEGER DEFAULT 65536,
singleton IN BOOLEAN DEFAULT FALSE,
shelflife IN INTEGER DEFAULT 0)
RETURN INTEGER;
DBMS_PIPE.SEND_MESSAGE (
pipename IN VARCHAR2,
timeout IN INTEGER DEFAULT MAXWAIT,
credential_name IN VARCHAR2 DEFAULT NULL,
location_uri IN VARCHAR2 DEFAULT NULL)
RETURN INTEGER;
プラグマ
pragma restrict_references(send_message,WNDS,RNDS);
パラメータ
表136-15 SEND_MESSAGEファンクションのパラメータ
パラメータ | 説明 |
---|---|
|
メッセージを設定するパイプの名前。 明示的なパイプを使用している場合、この名前は、 注意: |
|
パイプにメッセージを設定する間の待機時間(秒単位)。 デフォルト値は定数 |
|
パイプの最大サイズ(バイト単位)。 パイプ上のすべてのメッセージの合計サイズは、この数を超えることはできません。この最大値を超えると、そのメッセージはブロックされます。デフォルトは65536バイトです。 パイプの
|
|
singletonに singletonのデフォルト値は、 |
|
オプションで、暗黙的または明示的シングルトン・パイプにキャッシュされるメッセージの有効期限を秒単位で設定するために使用します。 デフォルト値の
|
|
メッセージの格納に使用するクラウド・ストアの資格証明名。 デフォルト値は |
|
メッセージの格納に使用しているクラウド・ストアの場所URL。
資格証明名を指定する場合は、 |
戻り値
表136-16 SEND_MESSAGEファンクションの戻り値
戻り値 | 説明 |
---|---|
|
成功。 パイプが存在し、パイプを作成するユーザーにそのパイプの使用が認可されている場合、Oracleは0(ゼロ)を戻して成功であることを示し、パイプ内のデータはそのまま残ります。
|
|
タイムアウトしました。 このプロシージャは、パイプでロックが取得できないか、またはパイプがいっぱいで使用できない理由でタイムアウトできます。暗黙的に作成されたパイプが空の場合、そのパイプは削除されます。 |
|
割込みが発生しました。 暗黙的に作成されたパイプが空の場合、そのパイプは削除されます。 |
|
既存のパイプをシングルトン・パイプに変換できませんでした。 複数の既存のメッセージがある暗黙的パイプは、シングルトン・パイプに変換できません。 シングルトン・パイプではない明示的なパイプの場合、 |
|
|
|
権限が不十分です。 同じ名前のパイプが存在し、別のユーザーがそのパイプを作成した場合、Oracleではエラー |
例外
表136-17 SEND_MESSAGEファンクションの例外
例外 | 説明 |
---|---|
|
アクセス権エラー。パイプに書込みを行うための権限が不十分です。パイプはプライベートで、別のユーザーが所有しています。 |
136.7.11 SET_CREDENTIAL_NAMEプロシージャ
このプロシージャでは、デフォルトの資格証明としてクラウドで使用されるグローバルcredential_name
変数を設定します。
構文
DBMS_PIPE.SET_CREDENTIAL_NAME (
credential_name IN VARCHAR2);
パラメータ
表136-18 SET_CREDENTIAL_NAMEプロシージャのパラメータ
パラメータ | 説明 |
---|---|
|
メッセージの格納に使用するクラウド・ストアの資格証明名。 |
136.7.12 SET_LOCATION_URIプロシージャ
このプロシージャでは、デフォルトの場所URIとしてクラウドで使用されるグローバルset_location_uri
変数を設定します。
構文
DBMS_PIPE.SET_LOCATION_URI (
location_uri IN VARCHAR2);
パラメータ
表136-19 SET_LOCATION_URIプロシージャ
パラメータ | 説明 |
---|---|
|
メッセージの格納に使用されるクラウド・ストアの場所URI。 |
136.7.13 UNIQUE_SESSION_NAMEファンクション
このファンクションは、現在データベースに接続しているすべてのセッション間での一意の名前を受け取ります。
同じセッションからこのファンクションを複数回コールしても、常に同じ値が戻されます。このファンクションは、SEND_MESSAGE
およびRECEIVE_MESSAGE
のコールにPIPENAME
パラメータを提供するのに役立ちます。
構文
DBMS_PIPE.UNIQUE_SESSION_NAME RETURN VARCHAR2;
プラグマ
pragma restrict_references(unique_session_name,WNDS,RNDS,WNPS);
戻り値
このファンクションは、一意の名前を戻します。戻される名前は、最大30バイトです。
136.7.14 UNPACK_MESSAGEプロシージャ
このプロシージャは、バッファから項目を取り出します。
RECEIVE_MESSAGE
をコールして、ローカル・バッファにパイプ情報を設定した後、UNPACK_MESSAGE
をコールします。
ノート:
UNPACK_MESSAGE
プロシージャは、VARCHAR2
、NCHAR
、NUMBER
またはDATE
タイプの項目を戻すためにオーバーロードされています。さらに、RAW
およびROWID
項目をアンパックするための2つのプロシージャがあります。
構文
DBMS_PIPE.UNPACK_MESSAGE ( item OUT VARCHAR2); DBMS_PIPE.UNPACK_MESSAGE ( item OUT NCHAR); DBMS_PIPE.UNPACK_MESSAGE ( item OUT NUMBER); DBMS_PIPE.UNPACK_MESSAGE ( item OUT DATE); DBMS_PIPE.UNPACK_MESSAGE_RAW ( item OUT RAW); DBMS_PIPE.UNPACK_MESSAGE_ROWID ( item OUT ROWID);
プラグマ
pragma restrict_references(unpack_message,WNDS,RNDS); pragma restrict_references(unpack_message_raw,WNDS,RNDS); pragma restrict_references(unpack_message_rowid,WNDS,RNDS);
パラメータ
表136-20 UNPACK_MESSAGEプロシージャのパラメータ
パラメータ | 説明 |
---|---|
|
アンパックされた次の項目をローカル・メッセージ・バッファから受け取るための引数。 |
例外
バッファに次の項目がない場合、または項目が要求されたタイプでない場合は、ORA-06556
または06559
が生成されます。