PL/SQLでは、外部プロシージャのC言語関数をコールできます。外部プロシージャは、Dynamic Link Library(DLL)またはSolarisの.soライブラリなどに格納されています。
外部プロシージャをサーバーで実行する場合、同一トランザクション中でSQLおよびPL/SQLが実行されるようにサーバーにコールバックできます。サーバーで外部プロシージャを実行すると、クライアントで実行した場合よりも処理速度が速く、外部システムおよびデータ・ソースと、データベース・サーバーとのインタフェースとして使用できます。
サーバー側の外部C言語関数を実行する場合は、関数内でREGISTER CONNECT埋込みSQL文を使用する必要があります。文の構文は次のとおりです。
EXEC SQL REGISTER CONNECT USING :epctx [RETURNING :host_context] ;
epctx
は、OCIExtProcContext
へのタイプ・ポインタの外部プロシージャ・コンテキストです。epctx
はPL/SQLによってプロシージャに渡されます。
host_context
は、外部プロシージャによって戻されるランタイム・コンテキストです。現在の設定は、デフォルト(グローバル)・コンテキストです。
REGISTER CONNECT文により、カレントのOracle接続およびトランザクションに対応付けられたOCIハンドル・セット(OCIEnv、OCISvcCtxおよびOCIError)が戻されます。これらのハンドルは、グローバルSQLLIBランタイム・コンテキストのPro*C/C++デフォルトである名前なし接続の定義に使用されます。このため、REGISTER CONNECTが、CONNECT文のかわりに使用されます。
後続の埋込みSQL文では、このOCIハンドル・セットを使用します。後続の埋込みSQL文は、グローバルSQLLIBランタイム・コンテキスト、名前なし接続に対して実行されます。これは、別々にプリコンパイルされたプログラム・ユニットにある場合でも同様です。コミットされていない変更は無効です。今後のバージョンでは、(非デフォルトの)ランタイム・コンテキストはオプションのRETURNING句で返されるようになります。
グローバル・ランタイム・コンテキストのアクティブなデフォルト接続はまだありません。すでに接続が確立しているときにREGISTER CONNECTを使用すると、ランタイム・エラーが戻されます。
関連項目:
OCI関数の詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください。
実際の業務では、外部プロシージャは複数の異なるアプリケーションから再利用できるようにすることをお薦めします。
外部プロシージャには次の規則があります。
外部プロシージャを使用できるのはCのみです。C++外部プロシージャはサポートされていません。
外部プロシージャ・コンテキストに接続した場合、接続を追加できません。ランタイム・エラーが発生します。
マルチスレッドの外部プロシージャはサポートされていません。EXEC SQL ENABLE THREADS文は使用できません。ランタイム・エラーが発生します。Pro*C/C++では、ここで説明している外部プロシージャを使用しない場合は、アプリケーションでのマルチスレッドがサポートされます。
DDL文を使用できません。ランタイム・エラーが発生します。
EXEC SQL COMMITおよびEXEC SQL ROLLBACKなどのトランザクション制御文を使用できません。
EXEC SQL OBJECTなどのオブジェクト・ナビゲーション文を使用できません。
EXEC SQL LOB文のポーリングを行うことはできません。
EXEC TOOLS文を使用できません。ランタイム・エラーが発生します。
外部プロシージャextp1
を作成する場合の簡単な例を示します。
外部Cプロシージャを格納するには、コードのコンパイルおよびリンクを行い、DLLなどのライブラリに格納します。
NT削除済ユーザー・コメント9561への参照
次のSQLコマンドを1回実行して、外部プロシージャextp1
を登録します。
CREATE OR REPLACE PROCEDURE extp1 AS EXTERNAL NAME "extp1" LIBRARY mylib WITH CONTEXT PARAMETERS(CONTEXT) ;
mylibは、プロシージャextp1が格納されるライブラリです。WITH CONTEXTが指定されているため、このプロシージャは、引数型OCIExtProcContext*
で暗黙的にコールされます。このコールでは、コンテキストが省略されていますが、プロシージャには渡されます。ただし、CREATE文のCONTEXTキーワードは、プレース・マーカーとして指定されています。
このコンテキスト・パラメータは、extp1
の内側のEXEC SQL REGISTER CONNECT文で参照されます。
外部プロシージャのコール方法の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。
外部プロシージャは、SQL*Plusから次のようにコールされます。
SQL> BEGIN INSERT INTO emp VALUES(9999,'JOHNSON','SALESMAN',7782, sysdate, 1200,150,10); extp1; END;
void extp1 (epctx) OCIExtProcContext *epctx; { char name[15]; EXEC SQL REGISTER CONNECT USING :epctx; EXEC SQL WHENEVER SQLERROR goto err; EXEC SQL SELECT ename INTO :name FROM emp WHERE empno = 9999; return; err: SQLExtProcError(SQL_SINGLE_RCTX,sqlca.sqlerrm.sqlerrmc,sqlca.sqlerrm.sqlerrml); return; }
SQLLIB関数SQLExtProcError()
を使用すると、外部Cプロシージャでエラーが発生した場合にPL/SQLに制御を戻すことができます。関数とその引数は次のとおりです。
SQLExtProcError (ctx, msg, msglen)
説明:
ctx (IN) sql_context *
この関数は、REGISTER CONNECT文のターゲットSQLLIBランタイム・コンテキストです。REGISTER CONNECT文は、この関数が起動される前に実行する必要があります。現在、グローバル・ランタイム・コンテキストのみがサポートされています。
msg (OUT) char *
エラー・メッセージのテキスト
msglen (OUT) size_t
メッセージのバイト単位の長さ
この関数が実行されると、SQLLIBによりOCIサービス関数OCIExtProcRaiseExcpWithMsgがコールされます。
メッセージは、SQLCAの構造体sqlerrm
から出力されます。SQLCAの構造およびsqlerrm
の説明は、SQLCAの構造体を参照してください。
SQLExtProcError()
の使用方法の例です。
void extp1 (epctx) OCIExtProcContext *epctx; { char name[15]; EXEC SQL REGISTER CONNECT USING :epctx; EXEC SQL WHENEVER SQLERROR goto err; EXEC SQL SELECT ename INTO :name FROM emp WHERE smpno = 9999; return; err: SQLExtProcError (SQL_SINGLE_RCTX, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrm.sqlerrml); printf("\n%*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); return; }