ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Enterprise Scheduler開発者ガイド
11g リリース1 (11.1.1.7)
B66615-04
  目次へ移動
目次

前
 
次
 

8 PL/SQLジョブの作成と使用

この章では、Oracle Enterprise Schedulerで使用するPL/SQLストアド・プロシージャを作成する方法と、Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するために実行する必要があるOracle Databaseタスクについて説明します。

PL/SQLプロシージャを作成してジョブ定義を定義すると、Oracle Enterprise Schedulerランタイム・サービスを使用して、PL/SQLプロシージャに対するジョブ・リクエストを発行できるようになります。

この章では、次の項目について説明します。

ランタイム・サービスの使用方法の詳細は、第14章「ランタイム・サービスの使用」を参照してください。

8.1 PL/SQLストアド・プロシージャ・ジョブ定義の使用の概要

Oracle Enterprise Schedulerを使用すると、Javaクラス、PL/SQLストアド・プロシージャ、分岐プロセスとして実行されるプロセス・リクエストなど、様々なタイプのジョブ・リクエストを実行できます。Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するには、次を実行する必要があります:

最後に、Oracle Enterprise Scheduler APIを使用するアプリケーションを作成したら、Oracle JDeveloperを使用してアプリケーションをデプロイして実行します。

実行時に、ジョブ・リクエストを発行した後、ジョブ・リクエストを監視および管理できるようになります。詳細は、第14章「ランタイム・サービスの使用」を参照してください。

Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャ・ジョブ・リクエストに非同期実行モデルを使用します。つまり、Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャを直接コールするのではなく、Oracle Enterprise Scheduler (Oracle Databaseに含まれる)を使用します。PL/SQLストアド・プロシージャ・ジョブ・リクエストを実行する準備が整うと、Oracle Enterprise Schedulerにより、即時に1回のみ実行されるOracle Enterprise Schedulerジョブが作成されます。このOracle Enterprise Schedulerジョブは、PL/SQLストアド・プロシージャを指定するアプリケーションを実行するコンテナ・インスタンスに関連付けられているOracle Enterprise Schedulerランタイム・スキーマ・ユーザーによって所有されます。最後に、Oracle Enterprise Schedulerジョブが実行されると、PL/SQLストアド・プロシージャが動的SQLを使用してコールされます。PL/SQLストアド・プロシージャが(正常な戻り値または例外の発生によって)完了すると、Oracle Enterprise Schedulerジョブが完了します。

8.2 Oracle Enterprise Scheduler用PL/SQLストアド・プロシージャの作成

Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するには、PL/SQLプロシージャに、Oracle Enterprise Schedulerアプリケーションで動作するための特定の特性がある必要があり、かつ、特定のOracle Database権限がPL/SQLストアド・プロシージャに割り当てられていることをDBAが確認する必要があります。

PL/SQLストアド・プロシージャの作成には、次のステップが含まれます。

8.2.1 正しいシグネチャを持つPL/SQLストアド・プロシージャの定義方法

Oracle Enterprise SchedulerからコールするPL/SQLストアド・プロシージャは、特定のシグネチャを持ち、次のような特定のプロシージャ・パラメータを含む必要があります。

PROCEDURE my_proc(request_handle IN VARCHAR2);

request_handleパラメータは、実行されるOracle Enterprise Schedulerリクエストの実行コンテキストを表す不透明な値です。

例8-1に、Oracle Enterprise Schedulerで使用するサンプルのHELLO_WORLDストアド・プロシージャを示します。

例8-1 HELLO_WORLD PL/SQLストアド・プロシージャ

create or replace procedure HELLO_WORLD( request_handle in varchar2 )
as
    v_request_id  number := null;
    v_prop_name  varchar2(500) := null;
    v_prop_int  integer := null;
begin
    -- Get the Oracle Enterprise Scheduler request ID being executed.
    begin
        v_request_id := ess_runtime.get_request_id(request_handle);
    exception
        when others then
            raise_application_error(-20000,
                'Failed to get request id for request handle ' ||
                request_handle || '. [' || SQLERRM || ']');
    end;
 
    -- Retrieve value of an existing request property.
    begin
        v_prop_name := 'mytestIntProp';
        v_prop_int := ess_runtime.get_reqprop_int(v_request_id, v_prop_name);
    exception
        when others then
            rollback;
            raise_application_error(-20001,
                'Failed to get request property ' || v_prop_name ||
                ' for Oracle Enterprise Scheduler request ID ' || v_request_id ||
                '. [' || SQLERRM || ']' );
    end;
 
    -- Update an existing request property with a new value.
    -- This procedure is responsible for commit/rollback of the update operation.
    begin
        v_prop_name := 'myJobdefProp';
        ess_runtime.update_reqprop_varchar2(v_request_id, v_prop_name,
                                            'myUpdatedalue');
        commit;
    exception
        when others then
            rollback;
            raise_application_error(-20002,
                'Failed to update request property ' || v_prop_name ||
                ' for Oracle Enterprise Scheduler request ID ' || v_request_id ||
                '. [' || SQLERRM || ']' );
    end;
end helloworld;
/

8.2.2 Oracle Enterprise Scheduler PL/SQLストアド・プロシージャでのランタイム例外の処理

Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャ・ジョブ・タイプに非同期実行モデルを使用します。Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャを直接コールするのではなく、Oracle Databaseに含まれるOracle Enterprise Schedulerを使用します。PL/SQLストアド・プロシージャ・リクエストを実行する準備が整うと、Oracle Enterprise Schedulerにより、即時に1回のみ実行されるOracle Enterprise Schedulerジョブが作成されます。このジョブは、PL/SQLストアド・プロシージャに関連付けられているアプリケーションを実行するコンテナ・インスタンスに関連付けられているOracle Enterprise Schedulerランタイム・スキーマ・ユーザーによって所有されます。PL/SQLストアド・プロシージャは、Oracle Enterprise Schedulerジョブの実行時に、動的SQLを使用してコールされます。PL/SQLストアド・プロシージャが(正常な戻り値または例外の発生によって)完了すると、Oracle Enterprise Schedulerジョブが完了します。

PL/SQLストアド・プロシージャでは、RAISE_APPLICATION_ERROR例外を発生させることによって、例外およびその他の問題を処理できます。RAISE_APPLICATION_ERRORでは、PL/SQLストアド・プロシージャのエラー・コードが-20000から-20999の範囲である必要があります。PL/SQLストアド・プロシージャで例外を発生させる必要がある場合は、RAISE_APPLICATION_ERRORを使用できます。RAISE_APPLICATION_ERRORには、-20000から-20999の範囲のエラー・コードが必要です。

表8-1に、PL/SQLストアド・プロシージャの結果に基づくOracle Enterprise Schedulerの状態を示します。

表8-1 PL/SQLストアド・プロシージャの結果の終了状態

最終状態 説明

SUCCEEDED

PL/SQLストアド・プロシージャが例外を発生させることなく正常な結果を返すと、その後のリクエスト完了時のエラーにかかわらず、リクエストの状態はSUCCEEDED状態に遷移します。

WARNING

PL/SQLストアド・プロシージャが例外とともに結果を返すと、リクエストの状態はその例外のSQLエラー・コードに基づいて決まります。

SQLエラー・コードが-20900から-20919の範囲の場合、リクエストはWARNING終了状態に遷移します。

ERROR

PL/SQLストアド・プロシージャが例外とともに結果を返すと、リクエストの状態はその例外のSQLエラー・コードに基づいて決まります。

-20900から-20919の範囲外のエラー・コードの場合は、リクエストはERROR終了状態に遷移します(この範囲内のエラー・コードはWARNINGを示します)。

-20920から-20929の範囲内の戻りコードの場合は、BUSINESSエラー・タイプを持つERROR状態になります。この場合、リクエストは自動再試行には左右されません。


8.2.3 PL/SQLストアド・プロシージャでのジョブ・リクエスト情報へのアクセス方法

Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャの操作で必要となる可能性のある特定の操作を実行するためのPL/SQLパッケージESS_RUNTIMEが提供されています。これらのプロシージャを使用してジョブ・リクエスト操作を実行し、Oracle Enterprise Schedulerランタイム・スキーマのジョブ・リクエスト情報を取得できます。たとえば、これらのランタイム・プロシージャを使用してリクエストを発行し、Oracle Enterprise Schedulerジョブ・リクエストに関連付けられているリクエスト情報を取得および更新できます。

次のサンプル・コードは、ESS_RUNTIMEプロシージャの使用方法を示します。

v_request_id := ess_runtime.get_request_id(request_handle);

このリクエストにより、ジョブ・リクエストに関連付けられているリクエストIDが取得されます。

ESS_RUNTIMEパッケージ内の特定のプロシージャでは、リクエスト・ハンドル・パラメータが必要であり、実行されるリクエストに関する情報を提供します(これらのプロシージャは、PL/SQLストアド・プロシージャ・リクエストを実行するPL/SQLストアド・プロシージャからのみコールする必要があります)。ESS_RUNTIMEパッケージ内の一部のプロシージャは、実行するリクエストのコンテキスト外からコールできます。これらのプロシージャには、リクエストIDパラメータを含めることができます。

8.2.4 PL/SQLストアド・プロシージャの定義に関する必知事項

Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを作成して使用する場合は、次のことに注意する必要があります。

  • Oracle Enterprise Schedulerリクエストが発行されるときにPL/SQLストアド・プロシージャが存在する必要はありませんが、リクエストを実行する準備が整ったときには、PL/SQLストアド・プロシージャが存在し、Oracle Enterprise Schedulerランタイム・スキーマ・ユーザーがコールできる必要があります。

  • PL/SQLストアド・プロシージャは、Oracle Enterprise Schedulerランタイム・スキーマと同じデータベース上に存在する必要があります。

8.3 PL/SQLストアド・プロシージャ用のOracle Databaseタスクの実行

Oracle Enterprise Schedulerで使用するPL/SQLストアド・プロシージャを作成したら、DBAがPL/SQLストアド・プロシージャをOracle Databaseにロードして、必要な権限を付与する必要があります。

8.3.1 PL/SQLストアド・プロシージャ権限の付与方法

DBAは権限を付与する前に、Oracle Databaseと、Oracle Enterprise Scheduler PL/SQLストアド・プロシージャ・リクエストを発行する、デプロイされたJava EEアプリケーションに関連付けられているOracle Enterprise Schedulerランタイム・スキーマを決定する必要があります。

PL/SQLストアド・プロシージャ権限を付与する場合は、次の定義を使用します。

ess_schema: Java EEアプリケーションに関連付けられているOracle Enterprise Schedulerランタイム・スキーマを指定します。

user_schema: アプリケーション・ユーザー・スキーマの名前を指定します。

PROC_NAME: Oracle Enterprise Schedulerジョブ・リクエストに関連付けられているPL/SQLストアド・プロシージャの名前を指定します。

Oracle Database権限を付与する手順は、次のとおりです。

  1. Oracle Databaseで、アプリケーション・ユーザー・スキーマにESS_RUNTIMEパッケージの実行権限を付与します。次に例を示します。

    GRANT EXECUTE ON ess_schema.ess_runtime to user_schema;
    
  2. Oracle Databaseで、ESS_RUNTIMEパッケージにプライベート・シノニムを作成します。これは、PL/SQLストアド・プロシージャで完全なschema_name.ESS_RUNIMEを使用するかわりに、単にESS_RUNTIMEとしてESS_RUNTIMEを参照できる便利なステップです。次に例を示します。

    create or replace synonym user_schema.ess_runtime for ess_schema.ess_runtime;
    
  3. Oracle Databaseで、Oracle Enterprise Schedulerランタイム・スキーマ・ユーザーにPL/SQLストアド・プロシージャの実行権限を付与します。

    GRANT EXECUTE ON user_schema.proc_name to ess_schema;
    

    たとえば、Oracle Enterprise Schedulerランタイム・スキーマがTEST_ORAESSで、アプリケーション・ユーザー・スキーマがHOWTOであり、PL/SQLプロシージャの名前がHELLO_WORLDである場合は、次のようなDBA操作が必要になります。

    GRANT EXECUTE ON test_oraess.ess_runtime to howto;
    create or replace synonym howto.ess_runtime for test_oraess.ess_runtime;
    GRANT EXECUTE ON howto.hello_world to test_oraess;
    

8.3.2 PL/SQLストアド・プロシージャ権限の付与に関する必知事項

ESS_RUNTIMEパッケージの権限を付与するDBAタスクについて示されている最初の2つのステップは、ESS_RUNTIMEパッケージがPL/SQLプロシージャにより参照される場合にのみ必要です。これらの2つのステップは、ESS_RUNTIMEパッケージがそのアプリケーション・ユーザー・スキーマから使用されることがない場合には必要ありません。示されている3番目のステップは、Oracle Enterprise Schedulerからユーザー定義のPL/SQLストアド・プロシージャをコールできるようにするものであるため、常に必要となります。

Oracle Enterprise Scheduler PL/SQLストアド・プロシージャ・ジョブで使用される、特定のアプリケーション・ユーザー・スキーマ内のすべてのPL/SQLストアド・プロシージャは、常に同じ(単一の)Oracle Enterprise Schedulerランタイム・スキーマに関連付けられている必要があります。これは技術的に必要ありませんが、DBAのセットアップが大幅に簡略化され、PL/SQLストアド・プロシージャでESS_RUNTIMEを参照する場合に、プロシージャでOracle Enterprise Schedulerランタイム・スキーマを明示的に指定する必要がなくなります。

8.4 PL/SQLジョブ・タイプのジョブ定義の作成および格納

Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するには、メタデータ・サービスを見つけて、ジョブ定義を作成する必要があります。ジョブ定義は、名前とジョブ・タイプを指定して作成します。ジョブ定義を作成するときには、特定のシステム・プロパティも設定する必要があります。これにより、メタデータ・サービスを使用してジョブ定義とその他の関連オブジェクトを格納できるようになります。

メタデータ・サービスの使用方法の詳細は、第6章「メタデータ・サービスの使用」を参照してください。

Oracle Enterprise Schedulerシステム・プロパティを使用して、PL/SQLストアド・プロシージャをコールするOracle Enterprise Schedulerジョブに特定の属性を指定できます。

これらのSystemPropertyプロパティは、SQLジョブ・タイプのPROCEDURE_NAMESQL_JOB_CLASSにのみ適用されます。

PROCEDURE_NAMEシステム・プロパティは、実行されるPL/SQLストアド・プロシージャの名前を指定します。ストアド・プロシージャの名前は、schema.nameという形式である必要があります。このプロパティは、ジョブ・タイプまたはジョブ定義のいずれかに対して指定する必要があります。

SQL_JOB_CLASSシステム・プロパティは、SQLジョブ・リクエストを実行するために使用されるOracle Enterprise Schedulerジョブに割り当てるOracle Enterprise Schedulerジョブ・クラスを指定します。このプロパティは、リクエストに使用されるOracle Enterprise Schedulerジョブが、特定のOracle Databaseリソース・コンシューマ・グループに関連付けられる必要があるか、データベース・サービスへのアフィニティを持つ必要がある場合を除き、指定する必要はありません。

Oracle Enterprise Schedulerでは、Oracle Enterprise Schedulerジョブを使用して、SQLジョブ・リクエストに対してPL/SQLストアド・プロシージャを実行します。Oracle Enterprise Schedulerジョブ・クラスは、データベース・サービスに対するアフィニティを持つ必要があるジョブ、またはOracle Databaseリソース・コンシューマ・グループに関連付けられるジョブに関連付けることができます。Oracle Enterprise Schedulerジョブ・クラスを使用して正常にジョブを作成するには、Oracle Enterprise Schedulerジョブ所有者に、そのジョブ・クラスに対するEXECUTE権限が必要です。

SQL_JOB_CLASSシステム・プロパティが指定されない場合、デフォルトのOracle Enterprise Schedulerジョブ・クラスがOracle Enterprise Schedulerジョブに使用されます。デフォルトのジョブ・クラスは、デフォルトのリソース・コンシューマ・グループに関連付けられます。これはデフォルト・サービスに属することになり、このことは、サービス・アフィニティを持たず、Oracle RAC環境ではクラスタ内のどのデータベース・インスタンスでもジョブを実行し得ることを意味します。Oracle Enterprise Scheduler SQLリクエストでこのデフォルト・ジョブ・クラスを使用するために必要な追加の権限付与はありません。

8.4.1 PL/SQLジョブ・タイプの作成方法

Oracle Enterprise SchedulerのJobTypeオブジェクトでは、実行タイプを指定し、ジョブ・リクエストの共通プロパティ・セットを定義します。1つのジョブ・タイプを定義して、1つ以上のジョブ定義で共有できます。Oracle Enterprise Schedulerでは、次の3つの実行タイプがサポートされています。

  • JAVA_TYPE: Javaで実装され、コンテナ内で実行されるジョブ定義に使用します。

  • SQL_TYPE: データベース・サーバーでPL/SQLストアド・プロシージャとして実行されるジョブ定義に使用します。

  • PROCESS_TYPE: 個別のプロセスとして実行される、バイナリおよびスクリプトのジョブ定義に使用します。

JobTypeを指定する場合、JobTypeに関連付けられる特性を定義するプロパティも指定できます。表8-2に、PL/SQLストアド・プロシージャ・ジョブ・タイプに適したSystemPropertiesを示します。

表8-2 PL/SQLストアド・プロシージャ・ジョブ・タイプ用のOracle Enterprise Schedulerシステム・プロパティ

システム・プロパティ 説明

PROCEDURE_NAME

PL/SQLジョブ実行の一部として実行するストアド・プロシージャの名前を指定します。

SQL_TYPEアプリケーションでは、これは必須のプロパティです。

SQL_JOB_CLASS

SQLジョブ・リクエストを実行するために使用されるOracle Enterprise Schedulerジョブに割り当てるOracle Enterprise Schedulerジョブ・クラスを指定します。

これは、SQL_TYPEジョブ・タイプのオプションのプロパティです。


PL/SQLジョブ・タイプを作成および格納するには、次を実行します:

  • JobTypeコンストラクタを使用して、String名とJobType.ExecutionType.SQL_TYPE引数を指定します。

  • 新しいJobTypeに適切なプロパティを設定します。

  • 第6.2項「メタデータ・サービスへのアクセス」に示されているように、メタデータ・ポインタを取得します。メタデータ・サービスのaddJobType()メソッドを使用して、JobTypeをメタデータに格納します。

  • メタデータ・リポジトリ内でメタデータ・オブジェクトを一意に識別するMetadataObjectIdを使用します。MetadataObjectIDには、一意の識別子を使用したメタデータ・オブジェクトの完全修飾名が含まれます。

サンプル・コードは、第8.4.3項「Oracle Enterprise SchedulerアプリケーションでのPL/SQLストアド・プロシージャの使用」を参照してください。

8.4.2 PL/SQLジョブ・タイプのジョブ定義の作成および格納方法

PL/SQLをOracle Enterprise Schedulerで使用するには、ジョブ定義を作成および格納する必要があります。ジョブ定義は、Oracle Enterprise Schedulerでジョブ・リクエストを定義する基本作業単位です。各ジョブ定義は、1つのジョブ・タイプにのみ属します。


注意:

ジョブ・タイプを指定してジョブ定義を作成した後で、タイプやジョブ定義名を変更することはできません。タイプまたはジョブ定義名を変更するには、新しいジョブ定義を作成する必要があります。


第8.4.3項「Oracle Enterprise SchedulerアプリケーションでのPL/SQLストアド・プロシージャの使用」には、ジョブ定義コンストラクタとジョブ・タイプを使用してジョブ定義を作成する方法が示されています。

8.4.3 Oracle Enterprise SchedulerアプリケーションでのPL/SQLストアド・プロシージャの使用

例8-2に、SQLジョブ・タイプに対してジョブ・タイプとジョブ定義アプリケーション・メタデータを作成するサンプル・コードを示します。

例8-2 PL/SQLストアド・プロシージャを使用したOracle Enterprise Schedulerのプログラム

import oracle.as.scheduler.JobType;
import oracle.as.scheduler.JobDefinition;
import oracle.as.scheduler.MetadataService;
import oracle.as.scheduler.MetadataServiceHandle;
import oracle.as.scheduler.MetadataObjectId;
import oracle.as.scheduler.ParameterInfo;
import oracle.as.scheduler.ParameterInfo.DataType;
import oracle.as.scheduler.ParameterList;
 
void createDefinition( )
{
   MetadataService metadata = ...
   MetadataServiceHandle mshandle = null;
 
   try
   {
      ParameterInfo pinfo;
      ParameterList plist;
 
      mshandle = metadata.open();
      
      // Define and add a PL/SQL job type for the application metadata.
      String jobTypeName = "PLSQLJobDefType";
      JobType jobType = null;
      MetadataObjectId jobTypeId = null;
 
      jobType = new JobType(jobTypeName, JobType.ExecutionType.SQL_TYPE);
 
      plist = new ParameterList();
      pinfo = SystemProperty.getSysPropInfo(SystemProperty.PROCEDURE_NAME);
      plist.add(info.getName(), pinfo.getDataType(), "HOWTO.HELLO_WORLD", false);
      pinfo = SystemProperty.getSysPropInfo(SystemProperty.PRODUCT);
      plist.add(pinfo.getName(), pinfo.getDataType(), "HOW_TO_PROD", false);
      jobType.setParameters(plist);
 
      jobTypeId = metadata.addJobType(mshandle, jobType, "HOW_TO_PROD");
 
      // Define and add a job definition for the application metadata.
      String jobDefName = "PLSQLJobDef";
      JobDefinition jobDef = null;
      MetadataObjectId jobDefId = null;
 
      jobDef = new JobDefinition(jobDefName, jobTypeId);
      jobDef.setDescription("Demo PLSQL Job Definition " + jobDefName);
 
      plist = new ParameterList();
      plist.add("myJobdefProp", DataType.STRING, "myJobdefVal", false);
      jobDef.setParameters(plist);
 
      jobDefId = metadata.addJobDefinition(mshandle, jobDef, "HOW_TO_PROD");
   }
   catch (Exception e)
   {
      [...]
   }
   finally
   {
      // always close metadata service handle in finally block
      if (null != mshandle)
      {
         metadata.close(mshandle);
         mshandle = null;
      }
   }
}