初心者の憂鬱:動的 SQL について調べてみた(後編)

初心者の憂鬱

サポート部の Yama-chan です。先日ツイッターで驚きのニュースを見ました。ゆりかもめ公式お知らせが次のような内容をツイートしました。

ゆりかもめ公式お知らせ:「設備メンテナンスで使用していたパソコンが引退しました。25 年前のノートパソコン「PC-9801」で、開業から使用していました。持ち運びには苦労しましたが、安全・安定運行を陰から支える、頼れる一台でした。おつかれさまでした。」

いや、ほんとうにお疲れさまでした。展示会で情報を収集するのが好きで、国際展示場へ行くときは必ずゆりかもめを利用していたので、25 年もゆりかもめの自動運転を裏で支えてきたことをあらためて感謝の気持ちでいっぱいです。そこで頭の裏に浮かんだのが PowerBuilder 。。。

PowerBuilder はいまでも機能が拡張され、新しい OS やデータベースへの対応が強化され進化し続けていますが、それでも時代遅れとか呼ばわれたりしています。しかしながら、ユーザーからは機能がこのままでいいから、新しい OS またはデータベースへの対応だけで十分という声をよく伺います。それだけ機能が成熟しているということなのかもしれません。また PowerBuilder ユーザーの場合、足らない機能はあの手この手を使って自分たちで作り上げてしまう、そんな声も良く伺います。

このニュースを見てから、時代遅れというより 30 年もたくさんの開発者に愛され、利用されつづけていることに誇りを感じるようになりました。これからも PowerBuilder をよろしくお願いします。

では、本題に入りましょう!


はじめに

前回のブログでは動的 SQL の前編として、動的 SQL の書式 1 と 2 について紹介しました。今回は後編として動的 SQL の書式 3 と 4 について紹介します。データベースへアクセスし、書式 1 と 2 では結果セットを返さないものでしたが、書式 3 と 4 は結果セットを返すものです。データベースへアクセスし、結果セットを取得し、データウィンドウまたはコントロールにデータを渡して表示することが可能です。


書式 3 :

まず、書式 3 ですが、特徴としては渡すパラメーターの数が事前に把握されていて、取得する結果セットのカラム数も同様に分かるようになっています。下記の例では検索条件として「where id > ?」 を指定して、「id」がパラメーターとして渡される値より大きいものを取得するものです。結果セットとして、カラム名「name」のみを取得するものです。取得された「name」が順番にリストボックスに追加され、利用者に選択できるようになっています。

下記は使用例のサンプルコードです。

// 使用している変数の定義および初期化
String ls_result = ""
Integer li_id = 0
String ls_sql
 
// カーソルの定義
DECLARE my_cursor DYNAMIC CURSOR FOR SQLSA;

// 動的 SQL で使用する SQL 文を定義
ls_sql = "SELECT name FROM USERS WHERE id > ?"

// SQL を元に SQLSA を用意
PREPARE SQLSA FROM :ls_sql;

// パラメーター:li_idを渡してカーソルをオープン
OPEN DYNAMIC my_cursor using :li_id;

// ループを回して、一件ずつデータを取り出して
// リストボックスに追加する。
FETCH my_cursor INTO :ls_result;
DO WHILE sqlca.sqlcode = 0
	lb_1.AddItem(ls_result)
	ls_result = ""
	FETCH my_cursor INTO :ls_result;
LOOP

// 最後に忘れずにオープンしたカーソルをクローズ
CLOSE my_cursor;
 

書式 4 :

最後に紹介する書式 4 は渡すパラメーターの数も受け取る結果セットのカラム数も可変のものです。この書式では入力した条件項目の数が不明ですが、渡すパラメーターを配列に順次追加していくことで対応可能です。

次のように二つの検索条件を指定している SQL 構文があるとします。

 Sqlstatement = "SELECT id, name " &
        + "FROM users WHERE id = ? and name=? "

条件が二つなので、以下のように SetDynamicParm 関数を使用して配列に条件を追加していきます。

 SetDynamicParm(SQLDA, 1, 1)
 SetDynamicParm(SQLDA, 2, "東京太郎")

下記はサンプルコードをまとめたものです。

// 変数の定義
string Sqlstatement, sValue
integer iValue

// 使用する SQL 構文の作成
Sqlstatement = "SELECT id, name " &
        + "FROM users WHERE id = ? and name = ? "

// SQLSA の準備
PREPARE SQLSA FROM :Sqlstatement ;

// SQLDA の定義
DESCRIBE SQLSA INTO SQLDA ;

DECLARE my_cursor DYNAMIC CURSOR FOR SQLSA ;

// パラメーター配列に条件を順次に追加
SetDynamicParm(SQLDA, 1, 1)
SetDynamicParm(SQLDA, 2, "東京太郎")

// SQLDAを使用してカーソルをオープン
OPEN DYNAMIC my_cursor USING DESCRIPTOR SQLDA ;

// FETCH でデータを取得
FETCH my_cursor USING DESCRIPTOR SQLDA ;

// データを取得する。
iValue = SQLDA.GetDynamicNumber(1)
sValue = SQLDA.GetDynamicString(2)

// カーソルをクローズ
CLOSE my_cursor ;
 

上記の例では、結果セットのデータを固定で数値と文字列を GetDynamicNumber と GetDynamicString で取得していますが、取得するデータの型が不明の場合は、case 文を使用してそれぞれの項目の型を確認し、データの型に合わせて取得する関数を使い分けることができます。

例:

CHOOSE CASE SQLDA.OutParmType[1]
    CASE TypeString!
        Stringvar = GetDynamicString(SQLDA, 1)
    CASE TypeInteger!
        Intvar = GetDynamicNumber(SQLDA, 1)
    CASE TypeLongLong!
        Longvar = GetDynamicDecimal(SQLDA, 1)
END CHOOSE
 

まとめ

以上で動的 SQL について前編と後編に分けて、簡単ですが例を交えて書式 1 から書式 4 まで紹介しました。初心者向けということで例もシンプルになっていますが、まず動的 SQL という実装方法もあることを頭の隅においていただければと思います。開発現場で実装方法を検討するときに動的 SQL を思い出して、機能を実現するために利用可能か検討していただければと思います。

以上、Yama-chan でした!

テクニカルブログ 一覧を見る
PowerBuilder マイグレーション