プライマリ・コンテンツに移動
Oracle® Database管理者リファレンス
18c for Microsoft Windows
E99714-01
目次へ移動
目次
索引へ移動
索引

前
次

外部プロシージャの構築について

Windowsで外部プロシージャを作成および使用する方法について説明します。

次のファイルは、ORACLE_HOME\rdbms\extprocにあります。

外部プロシージャの概要

外部プロシージャは、第3世代言語(Cなど)で記述されたファンクションで、PL/SQLルーチンまたはファンクションと同様に、PL/SQLまたはSQL内からコールできます。

外部プロシージャを使用すると、第3世代プログラミング言語の長所と機能をPL/SQLの環境内で利用できます。

注意:

Oracle Databaseでは、特殊なインタフェースであるコール仕様も提供しています。これにより、Cからコール可能な外部プロシージャを他の言語からコールできます。

外部プロシージャの主な利点は次のとおりです。

  • パフォーマンス。PL/SQLはSQLトランザクションの処理に向いているため、タスクによってはPL/SQLよりも第3世代プログラミング言語の方が効率的に行うことができます。

  • コードの再利用性。Dynamic Link Library(DLL)をサーバーまたはクライアント・ツールのPL/SQLプログラムから直接コールできます。

外部プロシージャを使用して、特定の処理を行えます。

  • 科学的問題や工学的問題の解決

  • データの分析

  • デバイスやプロセスのリアルタイム制御

注意:

外部プロシージャを処理するようにリスナーを構成する場合には、セキュリティ上の特別な予防手段が保証されます。

外部プロシージャを作成して使用するには、次の手順を実行します。

  1. Oracle DatabaseおよびOracle Net Servicesのインストールと構成

  2. 外部プロシージャの作成

  3. DLLのビルド

  4. 外部プロシージャの登録

  5. ライブラリ関連の権限を信頼できるユーザーのみに制限する

  6. 外部プロシージャの実行

注意:

  • DLLをビルドするには、Cコンパイラおよびリンカーがシステムにインストールされている必要があります。

  • 4番目と5番目のタスクの説明にある処理は、外部プロシージャの登録および実行の処理を自動化する、1つのSQLスクリプトにできます。これらの処理を結合したSQLスクリプトの例は、ORACLE_HOME\rdbms\extproc\extern.sqlを参照してください。

関連項目:

「高度なセキュリティのための外部プロシージャ構成の変更」および『Oracle Database Net Services管理者ガイド』を参照してください。

Oracle DatabaseおよびOracle Net Servicesのインストールと構成

Oracle DatabaseおよびOracle Netのインストールと構成について説明します。

Oracle Databaseのインストール

Windows ServerにOracle Databaseをインストールする方法について説明します。

以降の手順に従って、Windows Serverに次の製品をインストールします。

  • Oracle Database Enterprise Edition、Oracle Database Standard EditionまたはOracle Database Personal Edition。それぞれに、外部プロシージャからコールされるPL/SQLおよび外部プロシージャを実行するPL/SQL外部プロシージャ・プログラム(EXTPROC)が含まれています。

  • Oracle Net Services

  • Oracle Protocol Support

関連項目:

『Oracle Databaseインストレーション・ガイドfor Microsoft Windows』

Oracle Net Servicesの構成

データベース・サーバーのインストール時に、Oracle Net Configuration Assistantでは、外部プロシージャ・コール用のlistener.oraおよびtnsnames.oraファイルが構成されます。

アプリケーションから外部プロシージャがコールされると、Oracle Net Listenerによって、EXTPROCという外部プロシージャ・エージェントが起動されます。デフォルトでは、extprocプロセスは、サーバー・プロセスで直接通信します。リスナーによって確立されたネットワーク接続を使用して、アプリケーションからEXTPROCに次の情報が渡されます。

  • DLL名

  • 外部プロシージャ名

  • パラメータ(必要な場合)

次に、EXTPROCによってDLLがロードされ、外部プロシージャが実行されて、外部プロシージャから返された値が渡されます。

デフォルトのlistener.oraおよびtnsnames.oraファイルを上書きした場合は、次のファイルを手動で構成して、前述の外部プロシージャが起動するようにします。

  • ORACLE_HOME\network\admin\listener.ora

  • ORACLE_HOME\network\admin\tnsnames.ora

    注意:

    本番環境では、リスナーに追加セキュリティが必要な場合があります。

関連項目:

『Oracle Database Net Services管理者ガイド』

外部プロシージャの作成

第3世代プログラミング言語を使用して、作成したファンクションをDLLに組み込み、EXTPROCによって起動することができます。

次のコードは、Microsoft Visual C++で記述したFIND_MAXという外部プロシージャの簡単な例です。

注意:

外部プロシージャは、DLLに組み込まれるため、明示的にエクスポートする必要があります。この例では、DLLEXPORTという記憶域のクラス修飾子によって、ファンクションFIND_MAXをDynamic Link Libraryからエクスポートします。

#include <windows.h>
#define NullValue -1
/*
  This function tests if x is at least as big as y.
*/
long __declspec(dllexport) find_max(long 	x, 
 				short 	x_indicator, 
long 	y, 
short y_indicator, 
 				short *ret_indicator)
{
   /* It can be tricky to debug DLL's that are being called by a process
      that is spawned only when needed, as in this case.  
      Therefore try using the DebugBreak(); command.  
      This starts your debugger.  Uncomment the line with DebugBreak(); 
      in it and you can step right into your code.
   */
   /* DebugBreak();  */

   /* First check to see if you have any nulls. */
   /* Just return a null if either x or y is null. */

   if ( x_indicator==NullValue || y_indicator==NullValue) {
      *ret_indicator = NullValue;   
      return(0);
   } else { 
      *ret_indicator = 0;       /* Signify that return value is not null. */
      if (x >= y) return x;
      else return y;
   }
}

DLLのビルド

第3世代プログラミング言語で外部プロシージャを記述したら、該当するコンパイラとリンカーを使用してDLLをビルドして、前述したように外部プロシージャをエクスポートするようにしてください。

DLLのビルドとDLLの関数エクスポートに関する説明については、コンパイラおよびリンカーのマニュアルを参照してください。

ORACLE_HOME\rdbms\extprocに移動し、makeと入力すると、「外部プロシージャの作成」で作成した外部プロシージャFIND_MAXextern.dllというDLLに組み込むことができます。DLLをビルドした後は、システム内の任意のディレクトリに移動できます。

EXTPROCのデフォルトの動作では、DLLはORACLE_HOME\binまたはORACLE_HOME\libからのみロードされます。他のディレクトリからDLLをロードするには、環境変数EXTPROC_DLLSを、完全パスで修飾されたDLL名をコロン(:)で区切ったリスト(Windowsシステムではセミコロン区切り)に設定する必要があります。この環境変数を設定する優先方法は、listener.oraENVSパラメータを使用する方法です。

関連項目:

EXTPROCの詳細は、『Oracle Database開発ガイド』を参照してください。

外部プロシージャの登録

外部プロシージャを含むDLLをビルドした後は、外部プロシージャをOracle Databaseに登録する必要があります。

セキュリティを強化するために、EXTPROCプロセスを構成すると、CREDENTIALを介して認証できます。

Oracle DatabaseではCREATE LIBRARYコマンドの新しい2つの拡張がサポートされます。これは、CREDENTIAL句およびDIRECTORYオブジェクト・オプションです。CREDENTIAL句はユーザーのEXTPROCの実行を定義し、DIRECTORYオブジェクト・オプションはDLLを配置するディレクトリを指定します。

DLLにマップするためのPL/SQLライブラリを作成するには、次のようにします。

  1. listener.oraENVSパラメータに環境変数EXTPROC_DLLSを設定します。次に例を示します。
    SID_LIST_LISTENER =
     (SID_LIST =
      (SID_DESC =
       (SID_NAME=PLSExtProc)
       (ENVS=EXTPROC_DLLS=C:\app\oracle\product\18.0.0\dbhome_1\rdbms\extproc\extern.dll)
       (ORACLE_HOME=C:\app\oracle\product\18.0.0\dbhome_1)
       (PROGRAM=extproc)
      )
     )
    
  2. SQL*Plusを起動します。
    C:\> sqlplus
    
  3. 適切なユーザー名およびパスワードを入力してデータベースに接続します。
  4. CREATE LIBRARYコマンドでPL/SQLライブラリを作成します。
    DBMS_CREDENTIAL.CREATE_CREDENTIAL(...);
    CREATE DIRECTORY DLL_LOC as ...;
    CREATE LIBRARY externProcedures as 'extern.dll' in DLL_LOC credential the_credential;
    

    the_credentialDBMS_CREDENTIAL.CREATE_CREDENTIALの起動時に選択される名前です。

    SQL> CREATE LIBRARY externProcedures AS 'C:\app\oracle\product\18.0.0\dbhome_1\rdbms\ extproc\extern.dll';
    

    externProceduresは、別名のライブラリ(実際にはデータベースのスキーマ・オブジェクト)です。

    C:\app\oracle\product\18.0.0\dbhome_1\rdbms\extproc\extern.dll
    

    これは、Windowsオペレーティング・システムのdllextern.dllへのパスです。この例では、OracleベースとしてC:\app\oracle\product\18.0.0を、Oracleホームとしてdbhome_1を使用しています。

    注意:

    PL/SQLまたはSQLからPL/SQLライブラリの外部プロシージャをコールする必要のあるユーザーに対して、DBAは、PL/SQLライブラリへのEXECUTE権限を付与する必要があります。CREDENTIALおよびDIRECTORYオブジェクトの拡張での個別のEXECUTE権限が、それらが適切に機能するために必要です。

  5. PL/SQLプログラム・ユニットの仕様部を作成します。

    宣言部およびBEGIN...ENDブロックのかわりにEXTERNAL句を使用するPL/SQLサブプログラムを記述します。EXTERNAL句は、PL/SQLと外部プロシージャの間のインタフェースです。EXTERNAL句は、外部プロシージャに関する次の情報を示します。

    • 名前

    • DLLの別名

    • 使用したプログラム言語

    • コール標準(省略した場合は、デフォルトのCが使用される)

    次の例では、externProceduresはDLLの別名です。このライブラリに対するEXECUTE権限が必要です。コールする外部プロシージャはfind_maxです。二重引用符で囲まれている場合、大文字と小文字は区別されます。LANGUAGEでは、外部プロシージャを作成した言語を指定します。

    CREATE OR REPLACE FUNCTION PLS_MAX(
      x BINARY_INTEGER,
      y BINARY_INTEGER)
    RETURN BINARY_INTEGER AS EXTERNAL
      LIBRARY externProcedures
      NAME "find_max"
      LANGUAGE C
      PARAMETERS (
        x long,                  -- stores value of x
        x_INDICATOR short,       -- used to determine if x is a NULL value
        y long,                  -- stores value of y
        y_INDICATOR short,        -- used to determine if y is a NULL value
      RETURN INDICATOR short );  -- need to pass pointer to return value's
                                 -- indicator variable to determine if NULL
    -- This means that my function is defined as:
        -- long max(long x, short x_indicator,
        -- long y, short y_indicator, short * ret_indicator)

ライブラリ関連の権限を信頼できるユーザーのみに制限する

CREATE LIBRARYCREATE ANY LIBRARYALTER ANY LIBRARYおよびEXECUTE ANY LIBRARY権限と、EXECUTE ON library_nameの付与によって、ユーザーに大きな力が与えられます。

ライブラリへのPL/SQLインタフェースを作成する場合は、PL/SQLインタフェースにEXECUTE権限を付与するのみにしてください。基礎となるライブラリにEXECUTEを付与しないでください。ライブラリへのPL/SQLインタフェースを作成するためには、ライブラリに対するEXECUTE権限が必要です。しかしユーザーは、自分自身のスキーマで作成するライブラリに対して暗黙的にこの権限を持っています。EXECUTE ON library_nameの明示的付与が必要になることはほとんどありません。これらの権限の明示的付与は、信頼できるユーザーに対してのみ行ってください。決してPUBLICロールに対して付与しないでください。

外部プロシージャの実行

外部プロシージャを実行するには、外部プロシージャを登録したPL/SQLプログラム・ユニット(外部ファンクションの別名)をコールする必要があります。

これらのコールは、次のいずれにも含めることができます。

  • 無名ブロック

  • スタンドアロンおよびパッケージ・サブプログラム

  • オブジェクト型のメソッド

  • データベース・トリガー

  • SQL文(パッケージ・ファンクションのコールでのみ可能)

「外部プロシージャの登録」で、PL/SQL関数PLS_MAXを使用して、外部プロシージャfind_maxを登録しています。次の手順に従って、find_maxを実行します。

  1. PL/SQLファンクションPLS_MAXUseItというPL/SQLプロシージャでコールします。
    SET SERVER OUTPUT ON
    CREATE OR REPLACE PROCEDURE UseIt AS
             	a integer;
             	b integer;
             	c integer;
    BEGIN
             	a := 1;
             	b := 2;
             	c := PLS_MAX(a,b);
             	dbms_output.put_line('The maximum of '||a||' and '||b||' is  '||c);
    END;
    
  2. ルーチンを実行します。
    SQL> EXECUTE UseIt;