CALL
CALL ステートメントはプロシージャーを呼び出します。
呼び出し
このステートメントは、アプリケーション・プログラムに組み込むことができ、また対話式に呼び出すこともできます。 これは、動的に準備できる実行可能ステートメントです。
権限
このステートメントの権限 ID が保持する特権には、少なくとも以下の 1 つ が含まれていなければなりません。
- 呼び出すプロシージャーが SQL プロシージャーである場合
- そのプロシージャーに対する EXECUTE 特権。および、
- SQL プロシージャーが含まれるスキーマに対する USAGE 特権
- 呼び出すプロシージャーが Java™ 外部プロシージャーである場合
- Java クラスを含む統合ファイル・システム・ファイルに対する読み取り権限 (*R)
- 統合ファイル・システム・ファイルを検出するためにアクセスする必要があるすべてのディレクトリーに対する読み取りおよび実行権限 (*RX)
- 呼び出すプロシージャーが REXX 外部プロシージャーである場合
- そのプロシージャーに関連するソース・ファイルに対する *OBJOPR、*READ、および *EXECUTE システム権限
- ソース・ファイルが含まれるスキーマに対する USAGE 特権、および
- CL コマンドに対する *USE システム権限
- 呼び出すプロシージャーが外部プロシージャーではある
が、REXX または Java 外部プロシージャーではない場合
- そのプロシージャーに関連するプログラムまたはサービス・プログラムに対する *EXECUTE システム権限、および
- そのプロシージャーに関連するプログラムまたはサービス・プログラムが含まれるスキーマに対する USAGE 特権
- データベース管理者権限
- グローバル変数に対する READ 特権
- データベース管理者権限
- グローバル変数に対する WRITE 特権
- データベース管理者権限
SQL 特権に対応するシステム権限については、『関数またはプロシージャーへの権限を検査する際の対応するシステム権限』を参照してください。
構文
>>-CALL--+-procedure-name-+-------------------------------------> '-variable-------' >--+-----------------------------------+----------------------->< +-argument-list---------------------+ +-SQL-descriptors-------------------+ '-USING DESCRIPTOR--descriptor-name-' argument-list |--(--+----------------------------------------------+--)-------| | .-,----------------------------------------. | | V | | '---+----------------------+--+-expression-+-+-' '-parameter-name-- => -' +-DEFAULT----+ '-NULL-------' SQL-descriptors |--+------------------------------------------------------------+--> | .-SQL-. .-LOCAL--. | '-INTO--+-----+--DESCRIPTOR--+--------+--SQL-descriptor-name-' '-GLOBAL-' >--+-----------------------------------------------------------------+--| | (1) | | .-SQL-----. .-LOCAL--. | '-USING--+---------+--DESCRIPTOR--+--------+--SQL-descriptor-name-' '-GLOBAL-'
- SQL 記述子が USING 文節で指定されて INTO 文節が指定されない場合、USING DESCRIPTOR は許可されないため USING SQL DESCRIPTOR を指定しなければなりません。
説明
- procedure-name または variable
- 指定した procedure-name、または variable に含まれているプロシージャー名によって、呼び出したいプロシージャーを識別します。識別されたプロシージャーは、現行サーバーに存在していなければなりません。
変数 を指定する場合、
- その変数は、文字ストリング変数またはユニコード・グラフィック・ストリングでなければなりません。この変数は、グローバル変数にすることはできません。
- 標識変数を伴っていてはなりません。
- 変数内に含まれるプロシージャー名は左寄せでなければならず、その長さが変数の長さより短い場合は、右側にブランクを埋め込まなければなりません。
- プロシージャーの名前は、区切り文字付きの名前でない限り、大文字でなければなりません。
プロシージャー名は、修飾されなかった場合、パラメーターのパスと番号に基づいて暗黙的に修飾されます。 詳しくは、非修飾オブジェクト名の修飾を参照してください。
プロシージャー名が、DECLARE PROCEDURE ステートメントによって定義されたプロシージャーを識別し、かつ、現行サーバーが Db2® for i 製品である場合は、次のようになります。
- その DECLARE PROCEDURE ステートメントによって、外部プログラム、言語、および呼び出し規則の名前が決まります。
- そのプロシージャーのパラメーターの属性が、DECLARE PROCEDURE ステートメントによって定義されます。
DECLARE PROCEDURE がなく、 プロシージャー名が示しているプロシージャーが CREATE PROCEDURE ステートメントで定義されたものであり、 現行サーバーが Db2 for i である場合、次のようになります。
- その CREATE PROCEDURE ステートメントによって、外部プログラム、言語、および呼び出し規則の名前が決まります。
- そのプロシージャーのパラメーターの属性が、CREATE PROCEDURE ステートメントによって定義されます。
上記以外の場合、
- 現行サーバーが外部プログラム、言語、および呼び出し規則の名前を決定します。
- 現行サーバーが Db2 for
i である場合、
- 外部プログラム名は、外部プロシージャー名と同じであると想定されます。
- そのプログラムのプログラム属性情報が認識可能な言語を示している場合には、その言語が使用されます。 それ以外の場合は、言語は C であると見なされます。
- 呼び出し規則は GENERAL と見なされます。
- アプリケーション・リクエスターは、変数またはパラメーター・マーカーであるパラメーターはすべて INOUT であると想定します。変数以外のパラメーターは、すべて IN であると見なされます。
- パラメーターの実際の属性は、現行サーバーによって決定されます。
現行サーバーが Db2 for i である場合、パラメーターの属性は、CALL ステートメント上に指定された引数の属性と同じになります。 1
- argument-list
- パラメーターとしてプロシージャーに渡される値のリストを識別します。
n 番目の名前付きでない引数が、プロシージャー内の n 番目の
パラメーターに対応します。
(CREATE PROCEDURE または DECLARE PROCEDURE ステートメントを使用して) OUT として定義された各パラメーターは、 変数として指定する必要があります。OUT パラメーターに はデフォルトを指定できません。INOUT パラメーターにデフォルトが使用される 場合、そのデフォルト式は、プロシージャーへの入力用のパラメーターを 初期化するために使用されます。プロシージャーの終了時には、このパラメーターに 対して値は何も戻されません。
プロシージャーが呼び出されるときには、 デフォルト値を持つよう定義されていないすべてのパラメーターに対して引数が指定される 必要があります。名前付き構文を使用して、ある引数がパラメーターに代入される場合、それに続く引数もすべて名前付き構文を使用して代入される必要があります 。
日付、時刻、またはタイム・スタンプの特殊レジスター値への 引数リスト内での参照では、デフォルト式に 1 つのクロック読み取りが使用され、明示的引数内での参照には別のクロック読み取り が使用されます。
いずれかの引数が配列の場合、他のすべての引数はリテラル、特殊レジスター、NULL、または DEFAULT でなければなりません。
アプリケーション・リクエスターは、変数であるパラメーターがすべて Java 以外の INOUT パラメーターであると想定します。 ここでは、モードが変数参照で明示的に指定されている場合を除いて、 変数であるパラメーターはすべて IN であると想定されています。 変数以外のパラメーターは、すべて入力パラメーターであると見なされます。 パラメーターの実際の属性は、現行サーバーによって決定されます。
- parameter-name
- 引数値が割り当てられるパラメーターの名前。この名前は、プロシージャーに定義されているパラメーター名と一致しなければなりません。名前付き引数 は、引数リスト内に指定される順序とは無関係に、同じ名前を持つパラメーターに 対応します。引数が、名前によってパラメーターに割り当てられる場合、それ以降の引数もすべて名前によって割り当てられる必要があります。
- 名前付き引数は、一回だけ (暗黙的または明示的に) 指定される必要があります。
- 名前付き引数は、CREATE PROCEDURE ステートメントを使用して定義されたプロシージャーの呼び出しでのみ許可されます。
- expression
- 集約関数または列名を含まない、式で説明されているタイプの expression。拡張標識変数が使用可能である場合、DEFAULT および UNASSIGNED の拡張標識変数値は、その式に対して使用してはなりません。
- DEFAULT
- CREATE PROCEDURE ステートメント に定義されたデフォルトがプロシージャーへの引数として使用されることを 指定します。パラメーターのデフォルトが定義されていない場合は、NULL 値が使用されます。
- NULL
- NULL 値をプロシージャーへの引数として指定します。
- SQL-descriptors
- SQL 記述子が CALL で指定される場合、IN および INOUT パラメーターを持つプロシージャーでは SQL 記述子を USING 文節で指定する必要があり、OUT または INOUT パラメーターを持つプロシージャーでは SQL 記述子を INTO 文節で指定する必要があります。プロシージャーのすべてのパラメーターが INOUT パラメーターである場合は、両方の文節に同じ記述子を使用できます。
詳しくは、『CALL での複数の SQL 記述子』を参照してください。
- INTO
- CALL ステートメントとともに使用される出力変数の有効な記述を含む SQL 記述子を識別します。
CALL ステートメントを実行する前に、ALLOCATE DESCRIPTOR ステートメントを使用して記述子を割り振らなければなりません。
記述子ヘッダーの COUNT フィールドは、プロシージャーの OUT および INOUT パラメーターの数を反映して設定する必要があります。ステートメントの処理時に使用される変数について、TYPE のほか、DATETIME_INTERVAL_CODE、LENGTH、DB2_CCSID、
PRECISION、SCALE の該当する項目情報を設定する必要があります。
- LOCAL
- 記述子の名前の有効範囲はプログラム呼び出しのローカルであることを指定します。 情報は、このローカル有効範囲で既知の記述子から戻されます。
- GLOBAL
- 記述子の名前の有効範囲は SQL セッション全体であることを指定します。 情報は、同じデータベース接続を使用して実行するどのプログラムにも既知の記述子から戻されます。
- SQL-descriptor-name
- SQL 記述子の名前を指定します。名前は、指定の有効範囲を持つ既存の記述子を識別するものでなければなりません。
SQL 記述子に入る情報の説明については、GET DESCRIPTORを参照してください。
- USING
- CALL ステートメントとともに使用される入力変数の有効な記述を含む SQL 記述子を識別します。
CALL ステートメントを実行する前に、ALLOCATE DESCRIPTOR ステートメントを使用して記述子を割り振らなければなりません。
記述子ヘッダーの COUNT フィールドは、プロシージャーの IN および INOUT パラメーターの数を反映して設定する必要があります。ステートメントの処理時に使用される変数について、TYPE のほか、DATETIME_INTERVAL_CODE、LENGTH、DB2_CCSID、PRECISION、
SCALE の該当する項目情報を設定する必要があります。入力変数の DATA 項目と INDICATOR 項目 (NULL が使用される場合) を設定する必要があります。
- LOCAL
- 記述子の名前の有効範囲はプログラム呼び出しのローカルであることを指定します。
- GLOBAL
- 記述子の名前の有効範囲は SQL セッション全体であることを指定します。
- SQL-descriptor-name
- SQL 記述子の名前を指定します。名前は、指定の有効範囲を持つ既存の記述子を識別するものでなければなりません。
SQL 記述子内の情報の説明については、SET DESCRIPTORを参照してください。
- USING DESCRIPTOR descriptor-name
-
SQLDA を識別します。この SQLDA には、変数の有効な記述が入っていなければなりません。CALL ステートメントの処理に先立って、SQLDA の以下のフィールドをセットしておく必要があります。(REXX の場合は、規則が異なります。 詳しくは、「組み込み SQL プログラミング」トピック集を参照してください。)
- SQLN (SQLDA に用意する SQLVAR のオカレンスの数を示します。)
- SQLDABC (SQLDA 用に割り振る記憶域のバイト数を示します。)
- SQLD (ステートメントを処理するときに、SQLDA で使用する変数の個数を指示します。)
- SQLVAR の各オカレンス (変数の属性を指示します。)
SQLD には、ゼロ以上で SQLN 以下の値をセットしなければなりません。 この値は、CALL ステートメント内のパラメーター数と同じでなければなりません。 SQLDA によって n 番目に記述される変数は、準備済みステートメントの n 番目のパラメーター・マーカーに対応します。(SQLDA の説明については、SQLDA (SQL 記述子域)を参照してください。)
RPG/400® には、ポインターを設定する機能が用意されていないことに注意してください。 SQLDA はポインターを使用して適切な変数を見つけるので、ユーザーは、RPG/400 アプリケーションの外側でそのようなポインターを設定する必要があります。
Java プログラムでは、CALL ステートメントで USING DESCRIPTOR 文節を使用できません。
注
パラメーターの割り当て: CALL ステートメントが実行されると、 その各パラメーターの値は、プロシージャーの対応するパラメーターに (ストレージ割り当て規則を使用して) 割り当てられます。 デフォルト値を持つように定義されているパラメーター値は、プロシージャーを呼び出すときの引数リストから除外することが可能です。制御は、ホスト言語の呼び出し規則に従って、プロシージャーに渡されます。 プロシージャーの実行が完了すると、プロシージャーの各パラメーターの値が (SQL パラメーターのストレージ割り当て規則に基づいて、そうでなければ取得割り当て規則に基づいて) CALL ステートメントの対応するパラメーターに OUT または INOUTとして割り当てられます。割り当て規則の詳細については、割り当ておよび比較を参照してください。
グローバル変数: グローバル変数を指定することもできます。INOUT または OUT のパラメーターとしてグローバル変数を使用すると、そのグローバル変数が変更されます。
プロシージャー・シグニチャー: プロシージャーは、そのスキーマ、プロシージャー名、およびパラメーター数によって識別されます。 これはプロシージャー・シグニチャーと呼ばれ、データベース内でユニークである必要があります。プロシージャーごとにパラメーターの数が違っていれば、 1 つのスキーマに同じ名前のプロシージャーが複数存在しても構いません。
SQL パス: プロシージャーは、修飾名 (スキーマおよびプロシージャー名) を参照して呼び出すことができます。修飾名の後に、括弧に囲まれた引数のオプションのリストが続きます。 また、スキーマ名を指定せずにプロシージャーを呼び出すことも可能であり、 その場合は、同じ数のパラメーターを持つ異なるスキーマのプロシージャーが選択可能になります。 この場合、SQL パスを使用してプロシージャー解決を支援します。
プロシージャー解決: プロシージャー解決が どのように実行されるのかについて詳しくは、プロシージャー解決を参照してください。
プロシージャー内のカーソルと準備済みステートメント: 結果セット・カーソルでない、呼び出し先プロシージャー内でオープンされたカーソルは、プロシージャーの終了時にすべてクローズされ、呼び出し先プロシージャー内で準備されたステートメントはすべて破棄されます。プロシージャーの終了時にカーソルをオープンしたままにしておくために、CLOSQLCSR(*ENDACTGRP) を使用することもできます。詳しくは、SET OPTIONを参照してください。
プロシージャーの結果セット: プロシージャーから結果セットを返す方法は、3 つあります。
- プロシージャー内で SET RESULT SETS ステートメント が実行される場合、プロシージャー内で実行された最後の SET RESULT SETS ステートメント が結果セットを識別します。結果セットは、SET RESULT SETS ステートメントで指定した順序で戻されます。
- SET RESULT SETS ステートメントがプロシージャーで実行されない場合
- WITH RETURN 文節でカーソルが指定されていない場合、プロシージャーがオ ープンし、オープン状態のまま戻す各カーソルが、それぞれ 1 つの結果セッ トを識別します。結果セットは、カーソルがオープンされた順序で戻されます。
- WITH RETURN 文節でカーソルが指定されている場合、WITH RETURN 文節 で定義されたカーソルのうち、プロシージャーがオープンし、オープン状態 のまま戻す各カーソルが、それぞれ 1 つの結果セットを識別します。 結果セットは、カーソルがオープンされた順序で戻されます。
オープン・カーソルを使用して結果セットが戻される場合、現行カーソル 位置から始まる行が戻されます。
カーソル結果セットが SQL 配列タイプを参照している場合、 結果セットの処理時に配列参照が原因で正しくない結果になる可能性がある場合はエラーが 戻されます。
プロシージャー内のロック: 呼び出されたプロシージャーで獲得されたすべてのロックは、作業単位の終了まで保存されます。
プロシージャーからのエラー: プロシージャーは、 他の SQL ステートメントのように SQLSTATE を使用してエラー (または警告) を戻すことができます。 アプリケーションは、プロシージャーの呼び出し時に生じ得る SQLSTATE に留意する必要があります。 生じ得る SQLSTATE はプロシージャーをコード化する方法によって異なります。 プロシージャーは、プロシージャーの実行時にデータベース・マネージャーで問題が起きた場合、 '38' または '39' で始まる SQLSTATE を戻すこともできます。 このため、アプリケーションは、 CALL ステートメントの発行の結果生じる可能性のあるエラー SQLSTATE を処理する準備ができていなければなりません。
CALL ステートメントのネスティング: プロシージャーとして実行しているプログラム、 ユーザー定義の関数、またはトリガーで、CALL ステートメントを出すことができます。 プロシージャー、ユーザー定義の関数、またはトリガーでプロシージャー、ユーザー定義の関数、またはトリガーを呼び出すと、その呼び出しはネストされるものであると見なされます。 プロシージャーと関数のネストのレベル数には制限は設けられていませんが、トリガーの場合は、最大 200 レベルだけしかネストできません。
プロシージャーが何らかの照会の結果セットを戻す場合、その結果セットは、プロシージャーの呼び出し元に戻されます。 SQL CALL ステートメントがネストされた場合、その結果セットは、直前のネスト・レベルのプログラムだけに表示されます。 例えば、クライアント・プログラムがプロシージャー PROCA を呼び出すと、そのプロシージャーは、プロシージャー PROCB を呼び出します。 PROCA だけが PROCB によって戻された結果セットをアクセスすることができます。クライアント・プログラムは、照会の結果セットをアクセスすることはできません。
SQL や外部プロシージャーが呼び出されると、そのプロシージャーの作成時に定義された SQL データ・アクセスに対して属性が設定されます。 それらの属性に使用できる値は、次のとおりです。
NONE
CONTAINS
READS
MODIFIES
次のような場合に、2 番目のプロシージャーが現行プロシージャーの実行中に呼び出されるとエラーが出されます。
- 呼び出されたプロシージャーに SQL が使用されているが、呼び出しプロシージャーで SQL が許可されていない。
- 呼び出されたプロシージャーが SQL データを読み取っているが、呼び出しプロシージャーで SQL データの読み取りを許可していない。
- 呼び出されたプロシージャーが SQL データを変更したが、呼び出しプロシージャーで SQL データの変更を許可していない。
REXX プロシージャー: 呼び出す外部プロシージャーが REXX である場合、そのプロシージャーは、CREATE PROCEDURE または DECLARE PROCEDURE ステートメントを使用して宣言する必要があります。
変数は、REXX プロシージャー内では CALL ステートメントに使用することはできません。その代わりとして、CALL は、パラメーター・マーカーを使用して PREPARE と EXECUTE のオブジェクトにする必要があります。
CALL での複数の SQL 記述子: CALL で SQL 記述子が指定され、プロシージャーが IN または INOUT パラメーターと OUT または INOUT パラメーターを持つ場合は、2 つの記述子を指定する必要があります。 SQL 記述子に割り振る必要のある変数の数は、SQL 記述子の属性がどのように設定されるかと、パラメーターの各タイプの数によって異なります。
- 入力 SQL 記述子の属性が DESCRIBE INPUT を使用して設定されていて、出力 SQL 記述子の属性が DESCRIBE (OUTPUT) を使用して設定されている場合、SQL 記述子はプロシージャーを呼び出す前に、現行サーバーでの実際のプロシージャー定義に一致する属性を持つことになります。
この場合、出力 SQL 記述子には、OUT および INOUT パラメーターごとに変数が 1 つずつ含まれることになります。
同様に、入力 SQL 記述子には、IN および INOUT パラメーターごとに変数が 1 つずつ含まれることになります。
これが、CALL ステートメントで複数の SQL 記述子を指定する場合の推奨技法です。
- それ以外の場合は、プロシージャーを呼び出す前は現行サーバーでの実際のプロシージャー定義が不明であるため、プロシージャーが呼び出される時点では各パラメーターは INOUT であると見なされます。 これは、両方の SQL 記述子を指定する必要があり、各パラメーターが INOUT であると見なされるために両方の SQL 記述子が同数の変数を持つ必要があり、出力 SQL 記述子内の各変数の TYPE、DATETIME_INTERVAL_CODE、LENGTH、DB2_CCSID、PRECISION、 SCALE は入力 SQL 記述子内の対応する変数と厳密に同じでなければならないことを意味します。 こうしないと、エラーが戻されます。
また、複数の SQL 記述子が指定された場合、入力 SQL 記述子内の INOUT パラメーターに関連した DATA または INDICATOR 項目が、プロシージャーが呼び出されると変更される場合があります。 したがって、このような入力 SQL 記述子では、別のステートメントで使用する前に、DATA および INDICATOR 項目を再設定するために SET DESCRIPTOR が必要な場合があります。
例
例 1: プロシージャー PGM1 を呼び出し、2 つのパラメーターを渡します。
CALL PGM1 (:hv1,:hv2)
例 2: C において、INOUT_SQLDA という名前の SQLDA を使用して SALARY_PROC と呼ばれるプロシージャーを呼び出します。
struct sqlda *INOUT_SQLDA;
/* Setup code for SQLDA variables goes here */
CALL SALARY_PROC USING DESCRIPTOR :*INOUT_SQLDA;
例 3: 以下のステートメントを使用して、 Java プロシージャーをデータベース内で定義します。
CREATE PROCEDURE PARTS_ON_HAND (IN PARTNUM INTEGER,
OUT COST DECIMAL(7,2),
OUT QUANTITY INTEGER)
LANGUAGE JAVA PARAMETER STYLE JAVA
EXTERNAL NAME 'parts!onhand';
Java アプリケーションは、以下のコード・フラグメントを使用して、 接続コンテキスト 'ctx' においてこのプロシージャーを呼び出します。
...
int variable1;
BigDecimal variable2;
Integer variable3;
...
#sql [ctx] {CALL PARTS_ON_HAND(:IN variable1, :OUT variable2, :OUT variable3)};
...
このアプリケーション・コードのフラグメントは、CALL ステートメントで指定された procedure-name がデータベースにあり、外部名 'parts!onhand' を持っているため、 クラス parts にある Java メソッド onhand を呼び出します。
例 4: リレーショナル・データベース BRANCHRDB2 に対してプロシージャー PGM2 を呼び出し、1 つのパラメーターを渡します。
CALL BRANCHRDB2.SCHEMA3.PGM2 (:hv1)
CREATE PROCEDURE update_order(
IN IN_POID BIGINT,
IN IN_CUSTID BIGINT DEFAULT GLOBAL_CUST_ID,
IN NEW_STATUS VARCHAR(10) DEFAULT NULL,
IN NEW_ORDERDATE DATE DEFAULT NULL,
IN NEW_COMMENTS VARCHAR(1000)DEFAULT NULL)...
また、グローバル変数 GLOBAL_CUST_ID が 1002 という値に設定されているものとします。カスタマー 1002 の注文 5000 の状況を「出荷済み」に変更するためにプロシージャーを呼び出します。残りの引数をデフォルトの NULL 値にしておくことで、その他の注文データは現状のままとすることができます。CALL update_order (5000, NEW_STATUS => 'Shipped')
1001 という ID を持つカスタマーから連絡があり、購買注文 5002 の品物を受け取って満足していると示されます。注文を更新します。CALL update_order (5002,
IN_CUSTID => 1001,
NEW_STATUS => 'Received',
NEW_COMMENTS => 'Customer satisfied with the order.')