SQLの可変ファイル名
Question
作業ファイルで SQL を実行している SQLRPGLE プログラムがあります。このファイルは、ユーザーが実行している損失率レポートの出力オプション経由で構築されています。ファイル名を変数として SQL ステートメントに渡したいと考えています。これを簡単に行う方法はありませんか。出力ファイル名が変わるため、ファイルごとにすべての SQL ステートメントを複写したくありません。
Answer
組み込み SQL を RPG で使用する場合、静的 SQL ステートメントか、動的 SQL ステートメントを選択できます。静的ステートメントの方が速いですが、テーブル名やカラム名などのある情報はコンパイル時に既知でなければなりません。動的ステートメントは、実行時にほとんどすべてのことを行います。つまり、テーブル名とカラム名はステートメント実行まで既知である必要はないということです。
特定の要件によっては、静的 SQL あるいは動的 SQL のいずれかを使用できます。静的 SQL は、コンパイル時に作業の一部を行います。アクセス・プランがコンパイル時に生成または更新され、プログラム・オブジェクト自体の中に保存されます。これは、パフォーマンスに著しい影響を与える可能性があります。どのファイルにアクセスするかわからないと、アクセス・プランを生成できません。入力する SQL ステートメントは唯一のソース・コードであることを忘れないでください。このコードは、実行前に解釈され、コンパイルする必要があります。どのフィールドにアクセスするのか、またそれらのフィールドがファイルのどこにあるのか知る必要があるため、ファイル名はその大きな部分を占めます。
静的 SQL では、実行時に異なるファイルを指定する場合、OVRDBF を使用して、SQL を異なるファイルにポイントできます。
cmd = 'OVRDBF FILE(MYFILE) TOFILE(QTEMP/TEMPFILE)'; QCMDEXC(cmd: %len(cmd)); exec SQL declare MYCURSOR for select field1, field2 from MYFILE where AcctNo=:myAcctNo; exec SQL open MYCURSOR; exec SQL fetch next from MYCURSOR into :myDS; ...etc...
繰り返しますが、静的 SQL の最大のメリットはパフォーマンスです。この場合、アクセスしているファイル (TEMPFILE) は、あなたのステートメントがコンパイルされたファイル (MYFILE) とほとんど違いません。単に、まったく同じファイルの一時コピーです。ファイル名が違うだけなら、結果的にパフォーマンスが向上します。
動的 SQL は、実行時にほとんどすべての作業を行います。動的 SQL では、SQL ステートメント全体をオンザフライで構築し、実行できます。SQL エンジンは、実行時までステートメントについては何も認識していません。つまり、多少速度が遅くなるということです。(実行時にすべての作業を行う必要があるため、遅くなるのは理解できます。) ステートメントをオンザフライで構築し、フィールド名をオンザフライで指定して、ファイル名をオンザフライで指定できるなど、柔軟性が増しています。
(Java、PHP、C#、VB.NET など) 多数の言語では、動的 SQL しかサポートしていません。RPG は、静的と動的両方をサポートしています。
例えば、
mySql = 'select field1, field2 from ' + %trimr(FileName) + ' where AcctNo=?'; exec SQL prepare MYSTMT from :mySql; exec SQL declare MYCURSOR for MYSTMT; exec SQL open MYCURSOR using :myAcctNo; exec SQL fetch next from MYCURSOR into :myDS; ...etc...
プログラム変数を SQL ステートメントに挿入する方法は、動的 SQL では異なっている点に注意してください。静的 SQL では、単に VarName 変数をステートメントに挿入するよう :VarName をコーディングできます。動的 SQLではこれはできません。変数名は我々人間が楽をするためだけに存在している点を思い出してください。コンパイラーは、変数名をコンピューターのメモリー・バンクへのアクセスに置き換えるため、実行時には実際には変数名は存在しません。実行時にすべて行われる動的 SQL では、変数を指定する場所に (「パラメーター・マーカー」と呼ぶ) 疑問符 (?) を指定します。
カーソル open 上の「using」キーワードは、どの変数がパラメーター・マーカーに対応しているかを指定します。そのようにして、前述の例の :myAcctNo を、コンパイル時にメモリー位置に変換できます。実行時に、SQL は ? 文字を検索し、そのメモリー位置からのデータを挿入します。静的バリアントほど便利ではありませんが、SQL ステートメントを実行時に変更させてくれます。