[Lab 5d] DB2 でのアプリケーション開発 ( 組み込み SQL) 2011 年 06 月日本アイ ビー エム株式会社
Contents CONTENTS...2 1. はじめに...3 2. 内容...3 3. DB2 組み込み SQL への移行...3 3.1 準備...4 3.2 エラー処理用プログラムに関する処理...5 3.3 メインプログラムに関する処理...7 3.4 実行プログラムの生成...11 3.5 プログラムの実行...11 2
1. はじめに このハンズオンでは Oracle 用組み込み SQL プログラムを DB2 で稼動するように書き換え 実際に稼動することを確認します ファイルを編集する場合 vi や gedit が利用可能です gedit は Windows のメモ帳やワードパッドのように扱うことができます 2. 内容 Oracle 用組み込み SQL プログラムは 以下の 2 つのソース ファイルから構成されています lab5d_ora.pc ( メインプログラム ) 以下の 2 つの SQL 文を発行します 社員情報の取得 ( 静的 SQL) select empno,firstnme,lastname,salary,deptname,location from employee,department where employee.workdept=department.deptno and rownum <= 10 order by salary desc 社員番号を入力し 該当する社員の名前と誕生日を取得 ( 動的 SQL) select firstnme, birthdate from employee where empno=xxx lab5d_ora_err.pc ( エラー処理用プログラム ) 2 つの API が定義されています void SqlErrorTerminate() エラー表示後 ロールバックし プログラムを終了します void SqlErrorDisplay() エラー表示を行います DB2 への変換後のソース ファイル例として 以下の 2 つのファイルが提供されています lab5d_db2.sqc.hint lab5d_db2_err.sqc.hint 3. DB2 組み込み SQL への移行 この章では Oracle 用組み込み SQL プログラムを DB2 で稼動するように書き換え 実際に稼動することを確認します 3
3.1 準備 _ 環境の確認このハンズオンは db2inst1 ユーザーで行います 下記のコマンドを実行して db2inst1 ユーザーにスイッチし DB2 インスタンスを起動してください パスワードは db2inst1 です su - db2inst1 db2start DB2_COMPATIBILITAY_VECTOR がセットされていないことを確認してください db2set 存在していたら 下記のコマンドを発行して削除し DB2 を再起動してください db2set DB2_COMPATIBILITY_VECTOR= db2set db2stop db2start SAMPLE データベースを使用しますので SAMPLE データベースが作成されていることを確認してください db2 list database directory 作成されていなかったら 作成してください 以下のコマンドを発行すると SAMPLE データベースを作成し サンプル用のテーブルの作成 サンプル用のデータのロードを行います db2sampl _ 作業環境の準備作業用ディレクトリを作成し ソースコードをコピーします cd $HOME/sqllib mkdir lab5d cd lab5d cp /workshop/lab5d/*. アスタリスク (*) とピリオド (.) の間にスペースが入ります Oracle 用組み込み SQL プログラムを DB2 用にコピーします cp lab5d_ora.pc lab5d_db2.sqc cp lab5d_ora_err.pc lab5d_db2_err.sqc 4
3.2 エラー処理用プログラムに関する処理 _ エラー処理プログラムの書き換え 1. インクルード ファイル等の書き換え <sqlcpr.h> を <sql.h> に書き換えます #define SQLCA_STORAGE_CLASS extern を削除し <sqlca.h> のインクルードの後に extern struct sqlca sqlca; を付加します ( メインプログラムで宣言される sqlca を参照します ) /* #include <sqlcpr.h> */ #include <sql.h> /* #define SQLCA_STORAGE_CLASS extern */ #include <sqlca.h> extern struct sqlca sqlca; 2. ロールバックして切断処理 (EXEC SQL ROLLBACK WORK RELEASE) の変更 void SqlErrorTerminate() { /* 切断 */ /* EXEC SQL ROLLBACK WORK RELEASE; */ EXEC SQL ROLLBACK; EXEC SQL CONNECT RESET; } 3. エラーメッセージ取得処理の変更 Oracle の sqlglm() API に相当する DB2 の API は sqlaintp() ですが ここでは さらに sqlogstt() をコールし SQLSTATE メッセージも取得してみます void SqlErrorDisplay() { EXEC SQL WHENEVER SQLERROR CONTINUE; char emsg[128]; /* エラーメッセージ */ int buf_len = sizeof(emsg); int emsg_len; /* エラーメッセージの取得 */ /* * sqlglm(emsg, &buf_len, &emsg_len); 5
* printf("%.*s\n", emsg_len, emsg); */ sqlaintp(emsg, sizeof(emsg), 0, &sqlca); printf("%s\n", emsg); sqlogstt(emsg, sizeof(emsg), 0, sqlca.sqlstate); printf("%s\n", emsg); /* エラーコードの表示 */ printf("sqlcode(%d)\n", sqlca.sqlcode); } return; _ エラー処理プログラムのプリコンパイルプリコンパイルします ファイル名が 8 文字より多いので package using を使用します バインド ファイルは パッケージを削除後に再度登録する際に利用できるので バインド ファイルも生成しておきます db2 connect to sample db2 prep lab5d_db2_err.sqc bindfile package using lab5d_db2_err プリコンパイルでは 以下のようにエラーや警告がないことを確認します また C 言語のソース ファイル lab5d_db2_err.c および バインド ファイル lab5d_db2_err.bnd が作成されたことを確認します LINE MESSAGES FOR lab5d_db2_err.sqc ------ -------------------------------------------------------------------- SQL0060W "C" プリコンパイラーが処理中です SQL0091W プリコンパイルまたはバインドが "0" エラーと "0" 警告で終了しました _ 作成されたパッケージの確認以下のコマンドを発行して 作成されたパッケージを確認します db2 list packages パッケージ名が 8 文字までしか表示されないので 以下の SQL 文で再度確認してみます db2 "select pkgname from syscat.packages where pkgschema='db2inst1'" _ 作成されたパッケージのコンパイル 6
以下のコマンドを発行して プリコンパイルで生成された C 言語のソース ファイルをコンパイルします gcc -c lab5d_db2_err.c -I$HOME/sqllib/include エラーや警告が表示されないことを確認します 3.3 メインプログラムに関する処理 _ メインプログラムの書き換え 1. インクルード ファイルの書き換え <sqlcpr.h> を <sql.h> に書き換えます /* #include <sqlcpr.h> */ #include <sql.h> EXEC SQL INCLUDE SQLCA; 2. エラー処理用 API 呼び出しの変更以下の Oracle 用シンタックスを変更します EXEC SQL WHENEVER SQLERROR DO SqlErrorTerminate(); DB2 では GOTO 文を使用します 関数の最後にラベル SqlErrorTerminate: を定義し そこから SqlErrorTerminate() をコールするようにします /* EXEC SQL WHENEVER SQLERROR DO SqlErrorTerminate(); */ EXEC SQL WHENEVER SQLERROR GOTO SqlErrorTerminate; exit(0); SqlErrorTerminate: SqlErrorTerminate(); } 3. コミットして切断処理 (EXEC SQL COMMIT WORK RELEASE) の変更 7
/* 切断 */ /* EXEC SQL COMMIT WORK RELEASE; */ EXEC SQL COMMIT; EXEC SQL CONNECT RESET; exit(0); 4. VARCHAR 型の変更 VARCHAR 型を以下のように変更します /* VARCHAR last_name[15]; */ struct { short length; char data[15]; } last_name; 上記の変更に伴い printf() の該当する箇所を変更します /* printf("%s, %s, %.*s, ", empno, first_name, last_name.len, last_name.arr); */ printf("%s, %s, %.*s, ", empno, first_name, last_name.length, last_name.data); 5. DB 接続のロジックを変更します /* 接続準備 */ strcpy(user, "db2inst1"); strcpy(password, "db2inst1"); strcpy(dbname, "sample"); /* 接続 */ /* EXEC SQL CONNECT :user IDENTIFIED BY :password USING :dbname; */ EXEC SQL CONNECT TO :dbname USER :user USING :password; 6. フェッチで データがない場合の処理の変更 8
Oracle の以下の処理は DB2 で GOTO 文を指定することで実現可能ですが ここでは SQL 文実行後の SQLCODE を直接チェックするロジックを挿入してみます EXEC SQL WHENEVER NOT FOUND DO break; 上記をコメントアウトし SQL 文発行後に SQLCODE をチェックする以下のロジックを挿入します /* EXEC SQL WHENEVER NOT FOUND DO break; */ for (;;) { /* FETCH */ EXEC SQL FETCH cur INTO ; if (SQLCODE == 100) { break; } 2 番目の SQL 文の実行後は SQLCODE を直接チェックしています Oracle では デフォルトでは SQLCODE が 1403 の場合 データがないことを意味します DB2 では デフォルトでは 100 となりますので この値を変更します EXEC SQL FETCH cur2 INTO ; /* if (sqlca.sqlcode == 1403) { */ if (sqlca.sqlcode == 100) { 7. パラメーター マーカーの変更 /* strcpy(stmt, "select firstnme, birthdate from employee where empno=:p1"); */ strcpy(stmt, "select firstnme, birthdate from employee where empno=?"); _ エラー処理プログラムのプリコンパイルプリコンパイルします ファイル名が 8 文字より多いので package using を使用します バインド ファイルは パッケージを削除後に再度登録する際に利用できるので バインド ファイルも生成しておきます 9
db2 connect to sample db2 prep lab5d_db2.sqc bindfile package using lab5d_db2 結果として 複数のエラーが表示されています 最初に表示されているエラーは以下になります SQL0206N 使用されているコンテキストで "ROWNUM" は無効です SQLSTATE=42703 これは DB2 互換フィーチャーで ROWNUM の使用が無効になっているためです このように 静的 SQL のシンタックスは プリコンパイル時にチェックされます 以下のコマンドを発行して 有効にします db2set DB2_COMPATIBILITY_VECTOR=ORA db2set db2 terminate db2top db2start 再度 プリコンパイルしてみます プリコンパイルでは エラーがなくなったことを確認します また C 言語のソース ファイル lab5d_db2.c および バインド ファイル lab5d_db2.bnd が作成されたことを確認します _ 作成されたパッケージの確認以下のコマンドを発行して 作成されたパッケージを確認します db2 list packages 上記のコマンドで登録されているパッケージが 1 つ増えたことがわかりますが パッケージ名が 8 文字までしか表示されないので 以下の SQL 文で再度確認してみます db2 "select pkgname from syscat.packages where pkgschema='db2inst1'" _ 作成されたパッケージのコンパイル以下のコマンドを発行して プリコンパイルで生成された C 言語のソース ファイルをコンパイルします gcc -c lab5d_db2.c -I$HOME/sqllib/include エラーや警告が表示されないことを確認します 10
3.4 実行プログラムの生成 _ 実行プログラムの生成作成された 2 つのオブジェクト ファイルをリンクして 実行プログラムを生成します 以下のコマンドを入力します gcc -o lab5d_db2 lab5d_db2.o lab5d_db2_err.o -L$HOME/sqllib/lib32 -ldb2 エラーや警告が表示されないことを確認します 3.5 プログラムの実行 _ プログラムの実行準備プログラムの実行は あらかじめ DB2 に接続しておく必要はありません 以下のコマンドを入力し DB との接続を切断します db2 terminate _ プログラムの実行作成したプログラムを実行します./lab5d_db2 実行すると 10 件の社員情報がリストされます その後 EMPNO の入力が求められますので 上記のリストに存在する 最初の列に表示されている 6 桁の数字を入力してください そうすると 該当する社員の名前と誕生日が表示されます 入力した EMPNO に該当するレコードがない場合 (6 桁に満たない数字を入力したり 数字以外の文字を入力するなど ) 存在しないといったメッセージが表示されます _ エラー処理の確認 DB2 を停止して プログラムを実行します db2stop./lab5d_db2 そうすると 以下のエラーメッセージが表示されます SQL1032N start database manager コマンドが発行されていません SQLSTATE=57019 SQLSTATE 57019: リソースに問題があるため ステートメントが失敗しました SQLCODE(-1032) 11
Copyright IBM Corporation 2009 All Rights Reserved. 本書に含まれている情報は 正式な IBM のテストを受けていません また 明記にしろ 暗黙的にしろ なんらの保証もなしに配布されるものです この情報の使用またはこれらの技術の実施は いずれも 使用先の責任において行われるべきものであり それらを評価し 実際に使用する環境に統合する使用先の判断に依存しています それぞれの項目は ある特定の状態において正確であることが IBM によって調べられていますが 他のところで同じまたは同様の結果が得られる保証はありません これらの技術を自身の環境に適用することを試みる使用先は 自己の責任において行う必要があります 12