SQLで変数ファイル名を作成する
Question
作業ファイルで SQL を実行している SQLRPGLE プログラムがあるのですが、このファイルはユーザーが実行している損失率報告書の出力オプション経由で構築されています。ファイル名を変数として SQL ステートメントに渡そうと考えています。簡単に渡す方法はありませんか。出力ファイル名が変更されるので、ファイルごとにすべての SQL ステートメントを複写したくありません。
Answer
RPG で組み込み SQL を使用する場合、静的 SQL ステートメントと動的 SQL ステートメントから選択します。静的ステートメントの方が動作が速いですが、表名や列名など一部の情報はコンパイル時にわかっていなければなりません。動的ステートメントは実行時にほとんどすべてのことを行いますが、これはステートメントが実行されるまで表名と列名を知らなくてもかまわないことを意味します。特定の要件に応じて、静的か動的いずれかの SQL を使用できます。
静的 SQL はコンパイル時に一部の作業を行います。コンパイル時にアクセス・プランが生成または更新され、プログラム・オブジェクト自体の中に保存されます。これはパフォーマンスに大きな影響を与える可能性があります。どのファイルにアクセスしているかわからない場合は、アクセス・プランを生成できません。入力する SQL ステートメントはソース・コードに過ぎないことを忘れないでください。それは、実行する前に解釈するか、コンパイルする必要があります。それは、あなたがどのフィールドにアクセスしようとしていて、そのフィールドがファイルの中でどこにあるかを知る必要があるため、ファイル名は重要です。
静的 SQL では、実行時に異なるファイルを指定する場合、OVRDBF を使用して、異なるファイルをポイントできます。
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 ステートメントを変更できます。