11 PL/SQLジョブの作成と使用
この章では、Oracle Enterprise Schedulerで使用するPL/SQLストアド・プロシージャを作成する方法と、Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するために実行する必要があるOracle Databaseタスクについて説明します。
PL/SQLプロシージャを作成してジョブ定義を定義すると、Oracle Enterprise Schedulerランタイム・サービスを使用して、PL/SQLプロシージャに対するジョブ・リクエストを発行できるようになります。
この章の内容は次のとおりです。
ランタイム・サービスの使用方法の詳細は、「ランタイム・サービスの使用」を参照してください。
11.1 PL/SQLストアド・プロシージャ・ジョブ定義の使用の概要
Oracle Enterprise Schedulerを使用すると、Javaクラス、PL/SQLストアド・プロシージャ、分岐プロセスとして実行されるプロセス・リクエストなど、様々なタイプのジョブ・リクエストを実行できます。
Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するには、次を実行する必要があります:
-
Oracle Enterprise Schedulerで使用するPL/SQLストアド・プロシージャを作成または取得します。
-
PL/SQLストアド・プロシージャをOracle Databaseにロードして必要な権限を付与し、その他の必要なDBAタスクを実行します。
-
Oracle JDeveloperを使用してジョブ・タイプおよびジョブ定義オブジェクトを作成し、それらのオブジェクトをOracle Enterprise Schedulerアプリケーション・メタデータとともに格納します。
-
Oracle JDeveloperを使用して、PL/SQLストアド・プロシージャを実行および発行するOracle Enterprise Scheduler APIを持つアプリケーションを作成します。
最後に、Oracle Enterprise Scheduler APIを使用するアプリケーションを作成したら、Oracle JDeveloperを使用してアプリケーションをデプロイして実行します。
実行時に、ジョブ・リクエストを発行した後、ジョブ・リクエストをモニターおよび管理できるようになります。詳細は、「ランタイム・サービスの使用」を参照してください。
Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャ・ジョブ・リクエストに非同期実行モデルを使用します。つまり、Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャを直接コールするのではなく、Oracle Database Schedule (Oracle Database機能)を使用します。PL/SQLストアド・プロシージャ・ジョブ・リクエストを実行する準備が整うと、Oracle Enterprise Schedulerにより、即時に1回のみ実行されるOracle Database Schedulerジョブが作成されます。このOracle Database Schedulerジョブは、PL/SQLリクエストを実行するコンテナ・インスタンスに関連付けられているOracle Enterprise Schedulerランタイム・スキーマ・ユーザーによって作成され、アプリケーション・プロシージャ所有者によって所有されます。Oracle Database Schedulerジョブ・プロシージャは、Oracle Enterprise Schedulerランタイム・スキーマ・ユーザーによって所有されるPL/SQLラッパー・プロシージャです。最後に、Oracle Database Schedulerジョブの実行時、ラッパー・プロシージャは動的SQLを使用してアプリケーション・ストアド・プロシージャをコールします。PL/SQLストアド・プロシージャが(正常な戻り値または例外の発生によって)完了すると、Oracle Database Schedulerジョブが終了し、リモート実行が終了したOracle Enterprise Schedulerに通知するイベントを作成します。
11.2 Oracle Enterprise Scheduler用PL/SQLストアド・プロシージャの作成
Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するには、PL/SQLプロシージャに、Oracle Enterprise Schedulerアプリケーションで動作するための特定の特性がある必要があり、かつ、特定のOracle Database権限がPL/SQLストアド・プロシージャに割り当てられていることをDBAが確認する必要があります。
PL/SQLストアド・プロシージャの作成には、次のステップが含まれます。
-
Oracle Enterprise Schedulerで使用するための正しいシグネチャを持つPL/SQLストアド・プロシージャを定義します。
-
PL/SQLストアド・プロシージャをOracle Enterprise Schedulerで使用できるようにするために必要なDBAタスクを実行します。
11.2.1 正しいシグネチャを持つPL/SQLストアド・プロシージャの定義方法
Oracle Enterprise SchedulerからコールするPL/SQLストアド・プロシージャは、特定のシグネチャを持ち、次のような特定のプロシージャ・パラメータを含む必要があります。
PROCEDURE my_proc(request_handle IN VARCHAR2);
request_handle
パラメータは、実行されるOracle Enterprise Schedulerリクエストの実行コンテキストを表す不透明な値です。
例11-1に、Oracle Enterprise Schedulerで使用するサンプルのHELLO_WORLD
ストアド・プロシージャを示します。
例11-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, 'myUpdateValue'); 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; /
11.2.2 Oracle Enterprise Scheduler PL/SQLストアド・プロシージャでのランタイム例外の処理
PL/SQLストアド・プロシージャでは、RAISE_APPLICATION_ERROR
例外を発生させることによって、例外およびその他の問題を処理できます。RAISE_APPLICATION_ERROR
では、PL/SQLストアド・プロシージャのエラー・コードが-20000から-20999の範囲である必要があります。PL/SQLストアド・プロシージャで例外を発生させる必要がある場合は、RAISE_APPLICATION_ERROR
を使用できます。RAISE_APPLICATION_ERROR
には、-20000から-20999の範囲のエラー・コードが必要です。
表11-1に、PL/SQLストアド・プロシージャの結果に基づくOracle Enterprise Schedulerの状態を示します。
表11-1 PL/SQLストアド・プロシージャの結果の終了状態
最終状態 | 説明 |
---|---|
|
PL/SQLストアド・プロシージャが例外を発生させることなく正常な結果を返すと、その後のリクエスト完了時のエラーにかかわらず、リクエストの状態は |
|
PL/SQLストアド・プロシージャが例外とともに結果を返すと、リクエストの状態はその例外のSQLエラー・コードに基づいて決まります。 SQLエラー・コードが-20900から-20919の範囲の場合、リクエストは |
|
PL/SQLストアド・プロシージャが例外とともに結果を返すと、リクエストの状態はその例外のSQLエラー・コードに基づいて決まります。 -20900から-20919の範囲外のエラー・コードの場合は、リクエストは -20920から-20929の範囲内の戻りコードの場合は、 |
11.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パラメータを含めることができます。
11.2.4 PL/SQLストアド・プロシージャの定義に関する必知事項
Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを作成して使用する場合は、次のことに注意する必要があります。
-
Oracle Enterprise Schedulerリクエストが発行されるときにPL/SQLストアド・プロシージャが存在する必要はありませんが、リクエストを実行する準備が整ったときには、PL/SQLストアド・プロシージャが存在し、コールできる必要があります。
-
PL/SQLストアド・プロシージャは、Oracle Enterprise Schedulerランタイム・スキーマと同じデータベース上に存在する必要があります。
11.3 PL/SQLストアド・プロシージャ用のOracle Databaseタスクの実行
Oracle Enterprise Schedulerで使用するPL/SQLストアド・プロシージャを作成したら、DBAがPL/SQLストアド・プロシージャをOracle Databaseにロードして、必要な権限を付与する必要があります。
11.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権限を付与するには:
例として、Oracle Enterprise Schedulerランタイム・スキーマがTEST_ESS
で、アプリケーション・ユーザー・スキーマがHOWTO
であり、PL/SQLプロシージャの名前がHELLO_WORLD
である場合は、次のようなDBA操作は次のようになります。
GRANT EXECUTE ON test_ess.ess_runtime to howto; CREATE OR REPLACE SYNONYM howto.ess_runtime for test_ess.ess_runtime; GRANT EXECUTE ON test_ess.ess_job to howto; CREATE OR REPLACE SYNONYM howto.ess_job for test_ess.ess_job; GRANT EXECUTE ON test_ess.ESS_SCHJOB_PROC to howto;
11.3.2 PL/SQLストアド・プロシージャ権限の付与に関する必知事項
ESS_RUNTIME
パッケージの権限を付与するDBAタスクについて示されている2つのステップは、ESS_RUNTIME
パッケージがPL/SQLプロシージャにより参照される場合にのみ必要です。ESS_JOB
パッケージの権限の付与に使用されるDBAタスクについて示されている2つのステップは、ESS_JOB
パッケージがPL/SQLプロシージャにより参照される場合にのみ必要です。ESS_SCHJOB_PROC
プロシージャに示されているステップは、Oracle Enterprise Schedulerラッパー・プロシージャのコールを可能にするため、常に必要です。
Oracle Enterprise Scheduler PL/SQLストアド・プロシージャ・ジョブで使用される、特定のアプリケーション・ユーザー・スキーマ内のすべてのPL/SQLストアド・プロシージャは、常に同じ(単一の)Oracle Enterprise Schedulerランタイム・スキーマに関連付けられている必要があります。これは技術的に必要ありませんが、DBAのセットアップが大幅に簡略化され、PL/SQLストアド・プロシージャでESS_RUNTIME
を参照する場合に、プロシージャでOracle Enterprise Schedulerランタイム・スキーマを明示的に指定する必要がなくなります。
11.4 PL/SQLジョブ・タイプのジョブ定義の作成および格納
Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するには、メタデータ・サービスを見つけて、ジョブ定義を作成する必要があります。ジョブ定義は、名前とジョブ・タイプを指定して作成します。ジョブ定義を作成するときには、特定のシステム・プロパティも設定する必要があります。これにより、メタデータ・サービスを使用してジョブ定義とその他の関連オブジェクトを格納できるようになります。
メタデータ・サービスの使用方法の詳細は、「メタデータ・サービスの使用」を参照してください。
Oracle Enterprise Schedulerでは、Oracle Database Schedulerジョブを使用して、SQLジョブ・リクエストに対してPL/SQLストアド・プロシージャを実行します。Oracle Database Schedulerジョブ・クラスは、データベース・サービスに対するアフィニティを持つ必要があるジョブ、またはOracle Databaseリソース・コンシューマ・グループに関連付けられるジョブに関連付けることができます。Oracle Database Schedulerジョブ所有者は、ジョブ・クラスを使用してジョブを正常に作成するために、Oracle Database Schedulerジョブ・クラスについてEXECUTE
権限を持っている必要があります。
Oracle Enterprise Schedulerシステム・プロパティを使用して、PL/SQLストアド・プロシージャをコールするOracle Enterprise Schedulerジョブに特定の属性を指定できます。
これらのSystemPropertyプロパティは、SQLジョブ・タイプのPROCEDURE_NAME
とSQL_JOB_CLASS
にのみ適用されます。
PROCEDURE_NAME
システム・プロパティは、実行されるPL/SQLストアド・プロシージャの名前を指定します。ストアド・プロシージャ名は、owner.
nameの形式である必要があり、この場合のownerはジョブ・プロシージャのスキーマ所有者であり、nameはプロシージャ名です。このプロパティは、ジョブ・タイプまたはジョブ定義のいずれかに対して指定する必要があります。
SQL_JOB_CLASS
システム・プロパティは、SQLジョブ・リクエストの実行に使用されるOracle Database Schedulerジョブに割り当てられるOracle Database Schedulerジョブ・クラスを指定します。このプロパティは、リクエストに使用されるOracle Database Schedulerジョブが、特定のOracle Databaseリソース・コンシューマ・グループに関連付けられる必要があるか、データベース・サービスへのアフィニティを持つ必要がある場合を除き、指定する必要はありません。
SQL_JOB_CLASS
システム・プロパティが指定されていない場合、Oracle Enterprise Schedulerによって作成されるデフォルトのOracle Database Schedulerジョブ・クラスが、Oracle Database Schedulerジョブに使用されます。デフォルトのジョブ・クラスは、デフォルトのリソース・コンシューマ・グループに関連付けられます。これはデフォルト・サービスに属し、このことは、サービス・アフィニティがなく、Oracle RAC環境内で、クラスタ内のデータベース・インスタンスのいずれかがジョブを実行する可能性があることを意味します。Oracle Enterprise Scheduler SQLリクエストでこのデフォルト・ジョブ・クラスを使用するために必要な追加の権限付与はありません。
11.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
に関連付けられる特性を定義するプロパティも指定できます。表11-2に、PL/SQLストアド・プロシージャ・ジョブ・タイプに適したSystemProperties
を示します。
表11-2 PL/SQLストアド・プロシージャ・ジョブ・タイプ用のOracle Enterprise Schedulerシステム・プロパティ
システム・プロパティ | 説明 |
---|---|
|
PL/SQLジョブ実行の一部として実行するストアド・プロシージャの名前を指定します。
|
|
SQLジョブ・リクエストの実行に使用されるOracle Database Schedulerジョブに割り当てられるOracle Database Schedulerジョブ・クラスを指定します。 これは、 |
PL/SQLジョブ・タイプを作成および格納するには、次を実行します:
-
JobType
コンストラクタを使用して、String
名とJobType.ExecutionType.SQL_TYPE
引数を指定します。 -
新しい
JobType
に適切なプロパティを設定します。 -
「メタデータ・サービスへのアクセス」に示されているように、メタデータ・ポインタを取得します。メタデータ・サービスの
addJobType()
メソッドを使用して、JobType
をメタデータに格納します。 -
メタデータ・リポジトリ内でメタデータ・オブジェクトを一意に識別する
MetadataObjectId
を使用します。MetadataObjectID
には、一意の識別子を使用したメタデータ・オブジェクトの完全修飾名が含まれます。
サンプル・コードは、「Oracle Enterprise SchedulerアプリケーションでのPL/SQLストアド・プロシージャの使用」を参照してください。
11.4.2 PL/SQLジョブ・タイプのジョブ定義の作成および格納方法
PL/SQLをOracle Enterprise Schedulerで使用するには、ジョブ定義を作成および格納する必要があります。ジョブ定義は、Oracle Enterprise Schedulerでジョブ・リクエストを定義する基本作業単位です。各ジョブ定義は、1つのジョブ・タイプにのみ属します。
ノート:
ジョブ・タイプを指定してジョブ定義を作成した後で、タイプやジョブ定義名を変更することはできません。タイプまたはジョブ定義名を変更するには、新しいジョブ定義を作成する必要があります。
「Oracle Enterprise SchedulerアプリケーションでのPL/SQLストアド・プロシージャの使用」には、ジョブ定義コンストラクタとジョブ・タイプを使用してジョブ定義を作成する方法が示されています。
11.4.3 Oracle Enterprise SchedulerアプリケーションでのPL/SQLストアド・プロシージャの使用
この項では、SQLジョブ・タイプに対してジョブ・タイプとジョブ定義アプリケーション・メタデータを作成するサンプル・コードを示します。
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; } } }