組み込みSQLのすすめ ~連載|RPG Ⅳの魅力と可能性◎第10回

RPGプログラマーは
SQLを使い込んでいない

 この原稿を書いている時期はちょうど4〜5月の新入社員研修の時期で、私たちアイ・ラーニングも1年で一番活気のある季節です。お客様からお預かりした新入社員の方々が日々成長される姿を見ながら過ごす今の時期は、私たちもまた成長する時期でもあります。

 この新入社員研修のカリキュラムで、新入社員の方々が勉強されるプログラミング言語は、やはりJavaが中心です。大学や専門学校でもプログラミング言語と言えばJavaやCが中心で、私たちの時代、もう30年ほど前になりますが、昔は勉強で教わる言語がCOBOLやFORTRAN、アセンブラだった時代とは隔世の感があります。RPGは、グループとしてはCOBOLのほうに属します。COBOLもRPGもデータベース・ファイルを操作する機能をもっており、読み取ったレコードを直接プログラム内の変数に取り込むことができます。

 一方、JavaやCなど直接データベースを操作する機能がない言語では、SQLを使用します。必然的にJavaなどのオープン系言語のプログラマーの方はSQLをよく知っていますが、SQLを必要としないRPGプログラマーはSQLを知ってはいるものの、使い込んでいない傾向があるように思われます。5250画面からデータベースを操作する場合も、Queryを使うのが一番お手軽であることも理由としては大きいでしょう。

 

組み込みSQLは
シンプルにコーディングできる

 RPGではREADやCHAINの演算命令によるデータベース操作だけでなく、組み込みSQLが使用できます。これはJavaやC、PHPのSQLよりもはるかにシンプルにコーディングできるので、今後の開発で組み込みSQLを使用するメリットはたくさんあると思います。

 何よりも便利なのは、プログラム内のデータベースファイルのレコードの並び替え、レコードの選択、複数ファイルの結合などができることです。

 たとえば、帳票へのアウトプットを品目コードや事業所コードなどの特定のフィールドを基準に並び替えるには、プログラムがレコードを読み取る段階で、目的とする順序に並んでいなければなりません。そのための最も一般的な方法としては論理ファイルを作成し、その論理ファイルをプログラムに読ませる、またはOPNQRYFコマンドを使って動的にアクセスパスを作り、プログラムとアクセスパスを共有する、などの方法が挙げられます。

 レコード選択はプログラム内部で行うことが可能で、結合もプログラム内でセカンダリーファイルをCHAINで読み取るなどの方法でも可能です。レコードの選択と結合を論理ファイルで行うか、OPNQRYFで行うかはプログラマーにとっても悩ましいところです。いずれにしても論理ファイルのある・なしがプログラムの作り方に大きく影響しますし、OPNQRYFを使うならCLプログラムのほうにも影響が発生します。しかしSQLであればSQL文ひとつでレコード並び替え、レコード選択、結合などをすべてRPGプログラムの中で行えます。

 そしてSQL文の組み込み方ですが、これはRPGⅣだけでなく、RPGⅢでも可能です。Javaなどの他の言語と比べても、RPGの組み込みSQLの書き方はシンプルでコーディングしやすいものになっています。JavaやPHPでSQL文を発行する場合には、サーバーの接続、SQLステートメントの実行、すべて関数を使用するので、ステートメントがどうしても煩雑なものになってしまいます(図表1)。

 

SELECTステートメントの結果は
結果表に格納される

 SQLステートメントを実行したあと、取得したレコードは配列に格納されます。配列の1要素がデータベースの1フィールドになり、どちらかといえば配列というよりもデータ構造であり、この点でRPGプログラマーは混乱されるかもしれません。

 一方で、図表2はRPGⅢの組み込みSQLです。/EXEC SQLでSQLステートメントを組み込みます。このサンプルでは複数レコードを取得するので、このあとにFETCHステートメントを実行する必要がありますが、これはPHPでも同様で、のサンプルでもその部分は割愛してあります(RPGでのFETCHステートメントはこのあとお話しします)。それでもRPGの組み込みSQLでは接続も関数も必要ないので、PHPに比べてかなり見やすいことがおわかりいただけると思います。

 

 図表3は、サブファイルを使用した画面照会プログラムで、フリーフォームRPGで組み込みSQLを使用した例です。ここでは画面から入力された値が入るX1NAKNを使って、ファイルTOKMSPのフィールドTKNAKNの値がX1NAKNの値よりも等しいか、より大きいレコードを検索しています。

 

 RPGではSQLを使用する前にデータベースへの接続、という処理は必要ありませんが、データベースを使用する権限はプログラムを実行する人の権限がそのまま摘要され、セキュリティ面でも運用が容易です。フリーフォームRPGの文法としては、SQLステートメントはEXEC SQLで始まり、セミコロンで終わります。継続に+や、最後のEND-EXECは必要ありません。EXEC SQL は同一行に記入せねばなりませんが、SQLステートメントはブランクを使用できる場所で2行以上にまたがって記入できます。異なるSQLステートメントを同一行には記入できません。

 SQLが、SELECTステートメントで複数のレコードを選択した時、レコードは結果表に格納されます。結果表はシステムが生成するので定義の必要はありません。しかし結果表に格納しただけでは、取得したデータをまだプログラムで扱うことはできません。結果表の情報を1件ずつ取り出してRPGの変数に取り込み処理を行う、従来のREAD命令のような手続きがここで必要となります。結果表にアクセスするにはカーソルを使用します。カーソルを定義するには、DECLARE CURSOR ステートメントを用います。カーソル名はRPG変数ではないので、定義仕様書で定義する必要はありません。

 

レコードを処理するために
FETCHステートメント

 結果表に格納されたレコードを処理するためにFETCHステートメントを使用しますが、その前にOPENステートメントでカーソルをオープンします(図表4)。

 

 1回のFETCHステートメントで結果表の内容がRPGの変数に取り込まれ、カーソルは次の行にセットされます。図表3の例ではFETCHステートメントの取得結果はTOKというデータ構造に取り込まれます。図表4の95.00行以降のD#で始まるフィールドはデータ構造TOKのサブフィールドで、FETCHステートメントで取得したレコードをサブファイル上のフィールドに転送しています。

 また、88.00行目のDOU命令は終了条件が%EOFになっていますが、これはサブファイルがいっぱいになった時を示しています。91.00行目のSQLCODEは、SQLを使用したプログラムに自動的に生成されるSQL通信域の情報の1つで、SQLステートメントが正常に実行されると0が返されます。今回は読むべきデータがない時に、LEAVE命令でDOUの繰り返しから抜け出しています。

 こうして見ると、レコードを読み取ったあとの処理では従来のプログラムと大きく変化する部分はないことがおわかりいただけると思います。結果表に格納されたレコードをFETCHステートメントで取得する方法は、従来のREAD命令を使った方法とほとんど違和感がありません。そしてSQL文自体が従来の論理ファイルやOPNQRYFコマンドに代わる役割を果たすので、プログラミングもシンプルなものになっていくはずです。

 また関数も使わず、接続処理も必要ないのでコーディングが非常に楽です。このことはRPGプログラマーの方より、Javaなどのオープン系言語のプログラマーの方にとってより大きな魅力として伝わるのではないでしょうか。

 

著者|中村 潤 氏

株式会社アイ・ラーニング
IT研修本部 IBM製品研修部
ラーニング・アドバイザー

[i Magazine 2016年5月号掲載]

・・・・・・・・

◎ 連載|RPG Ⅳの魅力と可能性 目次