「選択/除外の論理ファイルを置き換えてシステム資源を有効に使おう!」で OPNQRYF による SELECT/OMIT の論理ファイルの書き換えを紹介しましたが、 埋め込み SQL を使うともっと自由度の高い書き換えが可能です。
埋め込み SQL って難しい、って思ったりしていませんか??
RPG をちゃんと書けるんだったら全然難しいことはないんです。
実はかなり機械的に変換が可能です。(今回は V5R4 のシステムでの実行例です)
まずは F 仕様書を DECLARE CURSOR に変えてやればいいだけです。
FTOKMSP IF E K DISK
を
exec sql DECLARE C1 CURSOR FOR
SELECT
tkbang, tknakj, tkadr1, tkadr2,
tktiku, tkpost, tkuzan, tkgend
FROM Tokmsp
ORDER BY tkbang ;
exec sql OPEN C1 ;
に変えるだけです。
カンタンでしょ??
F 仕様書には物理ファイル名もしくは論理ファイル名を指定しますが、カーソルとしては SQL を定義するわけです。
実行可能な SQL なら何でもいいので、検索条件の自由度は論理ファイルとは比較にならないくらい自由です。
ORDER BY でも GROUP BY でも JOIN でもいろいろ可能です。
プログラム内の処理に先立って何か読み込みデータの加工をしておきたい時に(プログラムを汎用的にしたいような場合、けっこうありますよね)、
事前に論理ファイルを作っておく必要もありませんし、論理ファイルよりもいろんなことが可能です。
SQL の場合、SELECT 句に読む必要があるカラムだけを指定できるので余計なカラムを読んでくることもありません。
読み込みに必要なバッファなどを小さくできるので実はパフォーマンスにはいいんです。
ファイルのオープンは OPEN xxxx でカーソルのオープンを行います。タイミングは自由です。
RPG でも USROPN がありますので、そのへんは同じですね。
あとは実行したいデータベース処理に応じて書き替え方は異なってきます。
カーソルの各レコード(行)については FETCH xxxx で読み込んで処理を行います。
read で読んでいるのであれば、FETCH でもう読んできたことになります。それだけで書き換えの主な部分は完了ですね。
(論理ファイルのお話をした時にちょっとふれましたが、RPG の READ/WRITE/UPDAT/DELET も "時代の産物" です。RPG でできたデータベース処理はすべて SQL でも可能で、SQL はそれ以上できる、と考えていいでしょう)
ループ制御も、RPG では標識や %eof 組み込み関数などを使用していると思いますが、
たいていはまったくそのままの形を保ったまま SQLSTATE を用いた判断に変えるだけで OK です。
たとえば、↓ は
DoU (%EOF) ;
read TOKMSP ;
If (%EOF) ;
leave ;
else ;
exsr SR_TOKMS ;
endIf ;
endDo ;
こうなります。
DoU (%subst(SQLSTATE:1:2) <> '00') ;
exec sql FETCH C1 INTO
:TKBANG, :TKNAKJ, :TKADR1, :TKADR2,
:TKTIKU, :TKPOST, :TKUZAN, :TKGEND
if %subst(SQLSTATE:1:2) = '02' ;
leave ;
else ;
exsr SR_TOKMS ;
endIf ;
endDo ;
SQLSTATE の上二桁は「クラス・コード」となっており、このレベルでループの制御はできますね。
問題判別時には SQLSTATE 値(五桁)を参照すればより詳しい原因がわかります。
ほとんど同じようにコーディングできることに注目! です。
では、それぞれの全文を見てみましょう。また例によって EOL の例題を ILE RPG に書き換えたものです。
H DATFMT(*JIS) DATEDIT(*YMD)
* BCH010 得意先マスターリストの印刷
FTOKMSP IF E K DISK RENAME(TOKMSP:TOKMSR)
FQPRINT O F 132 PRINTER OFLIND(*inOF)
D RECSU S 5 0
/free
//見出し印刷
except MIDASI ;
//得意先マスターの読み込み
DoU (%EOF) ;
read TOKMSP ;
If (%EOF) ;
leave ;
else ;
exsr SR_TOKMS ;
endIf ;
endDo ;
//終了処理
except SAISHU ;
*inLR = *on ;
return ;
BegSR SR_TOKMS ;
//ページ替えの確認
If (*inOF) ;
except MIDASI ;
reset *inOF ;
endIf ;
//明細の印刷
except MEISAI ;
RECSU += 1 ;
EndSR ;
/end-free
OQPRINT E MIDASI 02
O 51 ' **** 得意先マスター'
O 65 'リスト **** '
O 97 '作成日'
O UDATE Y 105
O PAGE Z 113
O 117 '頁'
O E MIDASI 03
O 8 '得意先'
O 90 '地 区 郵 便'
O E MIDASI 04 06
O 24 '番 号 得 意 先 名'
O 50 '住 所 (1) '
O 72 '住 所 (2) '
O 90 'コード 番 号'
O 103 '売掛金残高'
O 117 '信用限度額'
O E MEISAI 2
O TKBANG 6
O TKNAKJ 29
O TKADR1 51
O TKADR2 73
O TKTIKU 79
O TKPOST 89
O TKUZAN J 103
O TKGEND J 117
O E SAISHU 0
O 18 ' *レコード件数* '
O RECSU 1 25
こちらが埋め込みSQL を使用して書きかえたものです。ソースタイプは SQLRPGLE にする必要があります。(でないと構文チェックのエラーがたくさん出て大変なことになります)
該当する元の行は比較対照のために残しておきました。
H DATFMT(*JIS) DATEDIT(*YMD)
* BCH010得意先マスターリストの印刷
FQPRINT O F 132 PRINTER OFLIND(*inOF)
F*TOKMSP IF E K DISK RENAME(TOKMSP:TOKMSR)
*↑この F仕様書の定義が不要
D RECSU S 5 0
*↓ファイルのフィールドをワークの変数として使うため定義
D TOKDS E DS EXTNAME(TOKMSP)
/free
exec sql DECLARE C1 CURSOR FOR
SELECT tkbang,
tknakj,
tkadr1,
tkadr2,
tktiku,
tkpost,
tkuzan,
tkgend
FROM Tokmsp
ORDER BY tkbang ;
exec sql OPEN C1 ;
//見出し印刷
except MIDASI ;
//得意先マスターの読み込み
// DoU (%EOF) ;
DoU (%subst(SQLSTATE:1:2) <> '00') ;
// read TOKMSP ;
exec sql FETCH C1 INTO
:TKBANG,
:TKNAKJ,
:TKADR1,
:TKADR2,
:TKTIKU,
:TKPOST,
:TKUZAN,
:TKGEND ;
// If (%EOF) ;
if %subst(SQLSTATE:1:2) = '02' ;
leave ;
else ;
exsr SR_TOKMS ;
endIf ;
EndDo ;
//終了処理
except SAISHU ;
exec sql CLOSE C1 ;
*inLR = *on ;
Return ;
BegSR SR_TOKMS ;
//ページ替えの確認
If (*inOF) ;
except MIDASI ;
reset *inOF ;
endIf ;
//明細の印刷
except MEISAI ;
RECSU += 1 ;
EndSR ;
/end-free
OQPRINT E MIDASI 02
O 51 ' **** 得意先マスター'
O 65 'リスト **** '
O 97 '作成日'
O UDATE Y 105
O PAGE Z 113
O 117 '頁'
O E MIDASI 03
O 8 '得意先'
O 90 '地 区 郵 便'
O E MIDASI 04 06
O 24 '番 号 得 意 先 名'
O 50 '住 所 (1) '
O 72 '住 所 (2) '
O 90 'コード 番 号'
O 103 '売掛金残高'
O 117 '信用限度額'
O E MEISAI 2
O TKBANG 6
O TKNAKJ 29
O TKADR1 51
O TKADR2 73
O TKTIKU 79
O TKPOST 89
O TKUZAN J 103
O TKGEND J 117
O E SAISHU 0
O 18 ' *レコード件数* '
O RECSU 1 25
コンパイルのコマンドは CRTBNDRPG から CRTSQLRPGI に変わります。
サイズはちょっと増えます(144KB → 228KB )が、パフォーマンスは実はそんなに変わりません。
↓ がそれぞれを 3回ほど別のジョブで実行してみて、PEX のプロファイルで取った "Total DB CPU (μs)" の値です。
| 1回目 | 2回目 | 3回目 | |
| RPG | 33,872 | 19,920 | 29,448 |
| SQLRPG | 33,608 | 16,472 | 24,216 |
レスポンスタイム、CPU 使用率の観点から言って、あんまり差がないことがわかると思います。
(CPU 使用時間ですから、そのまま CPU の使用率にも直結しますね)
くりかえしになりますが、SQL をそのまま使えるので自由度があがりますし、JDBC で Java のプログラムを書いたり、ADO で VB を書いたりする時にスキルの共有になります。
また、STRSQL 画面などからテストしてみてすぐに結果が確認できる、という利点もあります。
けっこうカンタンにできる埋め込みSQL、活用しない手はないと思いますよ!!