DB2 アプリケーション 開発入門 コミュニティーによるコミュニティーのための学習書 RAUL F. CHONG, XIQIANG JI, PRIYANKA JOSHI, VINEET MISHRA, MIN WEI YAO 日本アイ・ビー・エム株式会社 訳・監訳 初版 2 DB2 アプリケーション開発入門 First Edition (July 2010) © Copyright IBM Corporation 2010. All rights reserved. IBM Canada 8200 Warden Avenue Markham, ON L6G 1C7 Canada 3 本書について 本書は、アメリカ合衆国において提供されている製品およびサービスを元に開発されています。 IBM は、本書に記載されている製品、サービス、機能に関して、アメリカ合衆国以外では提供していない場合 があります。各国で提供している内容については、各国の IBM にお問い合わせください。本書ではいくつか の IBM 製品、プログラム、サービスを利用した事例を紹介していますが、それは紹介している IBM 製品、プ ログラム、サービスのみを使うことを意図しているものではありません。同等の機能を持つ製品、プログラムや サービスで、IBM の知的所有権を侵害しないものを代わりに使用することも可能です。ただし、IBM 以外の製 品、プログラム、サービスに関する評価、確認は利用者自身が責任を負うものとします。 IBM は、本書に記述されている内容について、特許もしくは係属特許を有している場合があります。本書の提 供はいかなる項目に関して特許のライセンスを許可するものではありません。ライセンス関するお問い合わせ は以下までお願いします。 IBM Director of Licensing IBM Corporation North Castle Drive Armonk, NY 10504-1785 U.S.A. DBCS に関するお問い合わせは以下までお願いします。 Intellectual Property Licensing Legal and Intellectual Property Law IBM Japan, Ltd. 3-2-12, Roppongi, Minato-ku, Tokyo 106-8711 以 下 の 内 容 は 英 国 お よ び 各 国 の 法 律 と 矛 盾 を き た す 場 合 は 適 用 さ れ ま せ ん 。 INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 本書の内容については、技術的に不正確であったり、印刷上の誤植が含まれていたりする可能性があります。 変更は定期的に行われます。これらの変更は新版が提供される際に反映されます。IBM は本書にで紹介し ている製品、プラグラムについて予告なく改変することがあります。 本書で紹介している IBM 以外のサイトへのリンクは、利便性を目的として提供されており、リンク先のサイトに 関して何ら内容を保証するものではありません。それらのサイトは IBM 製品の一部として提供されているもの ではありません。利用者ご自身の責任でご活用ください。 IBM は、利用者により提供された情報に関して妥当性のあるものを判断した場合、利用者に責任を課すこと なく利用したり配布したりする場合があります。 4 DB2 アプリケーション開発入門 本書で紹介しているライセンスされたプログラムや資料は、IBM との間で取り交わした契約( IBM Customer Agreement や IBM プログラムご使用条件 (IPLA) のほか、それらと等価な契約)に基づいて提供されている ものとします。 本書に含まれるパフォーマンス・データは特定の環境におけるものであり、環境によって得られる結果は大き く異なる可能性があります。パフォーマンス測定は開発環境において実施されており、その結果は任意の環 境で得られることを保証するものではありません。情報を利用される方は、各自の環境で確認を行ってくださ い。 IBM 以外の製品の情報については、各製品の供給者より提供された製品発表や一般に公開された情報に 基づいています。 IBM はそれらの製品についてテストは行っておらず、パフォーマンスについても確認を行 っておりません。IBM 以外の製品については、各製品の供給元にご確認ください。 本書に記載されている内容につきましては、IBM の意向により予告なく変更されることがあります。 本書では、日常の業務でつかわれるデータや報告書のサンプルが含まれています。より分かりやすいサンプ ルを用意するためサンプルに個人名、企業名、ブランド、製品名が使われることがあります。これらの名称は すべて架空のものであり、実際の業務に似せた名前や住所を使っています。 著作権使用許諾: 本書には、ソース・コードを含むサンプル・プログラムが含まれており、さまざまなプラットフォーム上のプログラ ミング・テクニックを紹介しています。これらは開発、利用等の目的で IBM に利用料金を支払うことなく自由に コピー、改変、再配布することが可能です。これらのサンプルはあらゆる条件のもとでテストされたものではなく、 信頼性、有用性や機能に関して、IBM は何ら保証するものではありません。サンプル・プログラムは無保証の “AS IS “ として提供され、一切の保証はありません。IBM はこれによって生じる一切のトラブルに関して責任 を負わないものとします。 本書が参照している IBM 製品およびサービスは、あらゆる国において提供されていることを保証するもので はありません。 本書のソフト・コピーを利用される際は、写真やカラーイラストが正しく表示されない場合があります。 5 標章について IBM、IBM ロゴおよび ibm.com は、世界の多くの国で登録された International Business Machines Corp. の商標です。他の製品名およびサービス名等は、それぞれ IBM または各社の商標である場合があります。 現時点での IBM の商標リストについては、http://www.ibm.com/legal/copytrade.shtml をご覧ください。現 時点での IBM の商標リストについては、http://www.ibm.com/legal/copytrade.shtml の「Copyright and trademark information」をご覧ください。 Java およびすべての Java 関連の商標は、Sun Microsystems, Inc. の米国およびその他の国における 商標です。 Microsoft および Windows は、Microsoft Corporation の米国およびその他の国における商標です。 Linux は、Linus Torvalds の米国およびその他の国における登録商標です。 UNIX は、The Open Group の米国およびその他の国における登録商標です。 他の会社名、製品名およびサービス名等はそれぞれ各社の商標です。 目次 はじめに .......................................................................................................................... 13 本書の対象読者 ......................................................................................................... 13 本書の構成内容 ......................................................................................................... 13 コミュニティーのためのガイド ........................................................................................ 13 表記について ............................................................................................................. 13 さらに詳しく学ぶには................................................................................................... 14 著者 ................................................................................................................................ 17 貢献者 ............................................................................................................................ 18 謝辞 ................................................................................................................................ 18 訳者、監訳者 ................................................................................................................... 19 監訳者 ....................................................................................................................... 19 訳者 ........................................................................................................................... 19 第1章 DB2 アプリケーション開発の概要 ........................................................................... 21 1.1 DB2 アプリケーション開発 : 全体像........................................................................ 21 1.2 サーバー・サイドのアプリケーション開発.................................................................. 23 1.2.1 ストアード・プロシージャー............................................................................... 24 1.2.2 ユーザー定義関数 (UDF) .............................................................................. 24 1.2.3 トリガー .......................................................................................................... 25 1.3 クライアント・サイドのアプリケーション開発 ............................................................... 25 1.3.1 組み込み SQL............................................................................................... 26 1.3.2 静的 SQL と動的 SQL ................................................................................... 27 1.3.3 CLI と ODBC ................................................................................................ 29 1.3.4 JDBC, SQLJ および pureQuery .................................................................... 31 1.3.5 OLE DB ........................................................................................................ 33 1.3.6 ADO.NET ..................................................................................................... 34 1.3.7 PHP.............................................................................................................. 36 1.3.8 Ruby on Rails ............................................................................................... 36 1.3.9 Perl............................................................................................................... 37 1.3.10 Python ........................................................................................................ 37 1.4 XML と DB2 pureXML .......................................................................................... 38 1.5 Web サービス ....................................................................................................... 38 1.6 管理 API .............................................................................................................. 40 1.7 開発ツール ........................................................................................................... 40 1.7.1 Visual Studio ................................................................................................ 40 1.7.2 Eclipse.......................................................................................................... 41 1.7.3 Access および Excel ..................................................................................... 41 1.8 開発環境 .............................................................................................................. 42 1.8.1 クラウド上で提供している DB2 のサービス ....................................................... 42 1.8.2 VMware 向け DB2 Express-C 仮想アプライアンス.......................................... 46 1.9 サンプル・プログラム .............................................................................................. 46 1.10 演習 ................................................................................................................... 47 8 DB2 アプリケーション開発入門 1.11 まとめ ................................................................................................................. 47 1.12 確認問題 ............................................................................................................ 47 第2章 – DB2 pureXML................................................................................................... 49 2.1 データベースでの XML の利用 .............................................................................. 50 2.2 XML データベース ................................................................................................ 50 2.2.1 XML 対応(XML-enabled)データベース .......................................................... 50 2.2.2 ネイティブ XML データベース ......................................................................... 51 2.3 DB2 における XML ............................................................................................... 52 2.3.1 pureXML 技術の優位点 ................................................................................. 53 2.3.2 XPath 基本 ................................................................................................... 55 2.3.3 XQuery 基本 ................................................................................................. 58 2.3.4 XML 文書の挿入 ........................................................................................... 60 2.3.5 XML データの照会......................................................................................... 63 2.3.6 SQL/XML による結合 ..................................................................................... 70 2.3.7 XQuery による結合 ........................................................................................ 71 2.3.8 更新と削除操作 ............................................................................................. 71 2.3.9 XML インデックス ........................................................................................... 73 2.4 XML スキーマを用いた作業................................................................................... 75 2.4.1 XML スキーマの登録...................................................................................... 75 2.4.2 XML スキーマの妥当性検査 ........................................................................... 77 2.4.3 他の XML サポート......................................................................................... 78 2.5 演習 ..................................................................................................................... 79 2.6 まとめ ................................................................................................................... 80 2.7 確認問題 ......................................................................................................... 80 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス...... 83 3.1 ストアード・プロシージャー: 概要............................................................................. 84 3.2 IBM Data Studio の利用....................................................................................... 85 3.2.1 プロジェクトの作成.......................................................................................... 86 3.2.2 ストアード・プロシージャーの作成. ................................................................... 88 3.3 SQL PL ストアード・プロシージャーの基礎 .............................................................. 92 3.3.1 ストアード・プロシージャーの構造 .................................................................... 92 3.3.2 任意のストアード・プロシージャー属性 ............................................................. 93 3.3.3 パラメーター................................................................................................... 93 3.3.4 SQL PL ストアード・プロシージャーのコメント.................................................... 94 3.3.5 コンパウンド・ステートメント............................................................................... 94 3.3.6 変数の宣言.................................................................................................... 95 3.3.7 代入文 .......................................................................................................... 95 3.3.8 カーソル ........................................................................................................ 96 3.3.9 フロー制御..................................................................................................... 96 3.3.10 エラーおよび条件ハンドラー ......................................................................... 97 3.3.11 ストアード・プロシージャーの呼び出し ............................................................ 99 3.3.12 動的 SQL ...................................................................................................101 3.4 Java ストアード・プロシージャー ............................................................................102 3.5 ユーザー定義関数: 概要 ......................................................................................103 9 3.5.1 スカラー関数................................................................................................ 104 3.5.2 表関数......................................................................................................... 105 3.6 トリガー: 概要 ...................................................................................................... 106 3.6.1 トリガーのタイプ............................................................................................ 106 3.7 Data Web サービス............................................................................................. 109 3.8 演習 ................................................................................................................... 119 3.9 まとめ ................................................................................................................. 121 3.10 確認問題 .......................................................................................................... 121 第 4 章 – Java によるアプリケーション開発...................................................................... 123 4.1 Java - DB2 アプリケーション: 全体像 ................................................................... 123 4.2 環境の準備......................................................................................................... 124 4.2.1 DB2 JDBC ドライバーと SQLJ ドライバー...................................................... 125 4.3 JDBC プログラミング............................................................................................ 127 4.3.1 DB2 データベースへの接続 ......................................................................... 128 4.3.2 SQL ステートメントの実行 ............................................................................. 131 4.3.3 結果の取得.................................................................................................. 141 4.3.4 SQL エラーと警告の処理 ............................................................................. 142 4.3.5 接続の切断.................................................................................................. 144 4.3.6 XML の利用方法 ......................................................................................... 144 4.4 SQLJ プログラミング ............................................................................................ 148 4.4.1 SQLJ の構文............................................................................................... 148 4.4.2 Connection コンテキスト ............................................................................... 148 4.4.3 実行コンテキスト........................................................................................... 150 4.4.4 イテレーター ................................................................................................ 151 4.4.5 JDBC と SQLJ の同時利用 .......................................................................... 153 4.4.6 SQLJ プログラムの準備................................................................................ 154 4.5 pureQuery ......................................................................................................... 158 4.6 演習 ................................................................................................................... 159 4.7 まとめ ................................................................................................................. 160 4.8 確認問題 ............................................................................................................ 160 第 5 章 C/C++でのアプリケーション開発.......................................................................... 163 5.1 C/C++ DB2 アプリケーション: 全体像................................................................... 163 5.2 環境の設定......................................................................................................... 164 5.2.1 サポートされるコンパイラー............................................................................ 165 5.2.2 C/C++環境の設定 ...................................................................................... 165 5.3 組み込み SQL の C/C++ アプリケーション の開発................................................. 168 5.3.1 ソース・ファイルの拡張子 .............................................................................. 169 5.3.2 C/C++における SQL データ・タイプ............................................................... 169 5.3.3 組み込み SQL C/C++アプリケーションの開発手順 ........................................ 170 5.3.4 組み込み SQL の C/C++ アプリケーションの例.............................................. 172 5.3.5 C/C++ の組み込み SQL アプリケーションの構築 ........................................... 183 5.5 ODBC/CLI で C/C++ アプリケーションを開発する ................................................. 190 5.5.1 CLI/ODBC アプリケーションのための追加の環境設定 .................................... 190 5.5.2 ハンドル....................................................................................................... 192 10 DB2 アプリケーション開発入門 5.5.3 ODBC/CLI アプリケーションの開発手順 .........................................................193 5.5.4 ODBC/CLI アプリケーションの構築 ................................................................211 5.6 DB2 の C/C++ アプリケーション内で XML を処理する............................................213 5.7 演習 ....................................................................................................................213 5.8 まとめ ..................................................................................................................214 5.9 確認問題 .............................................................................................................214 第 6 章 – .NET によるアプリケーション開発 ......................................................................217 6.1.NET による DB2 アプリケーション: 全体像.............................................................217 6.2 ADO.NET データ・アーキテクチャー .....................................................................218 6.2.1 ADO.NET 用のデータ・プロバイダー..............................................................219 6.2.2 ADO.NET の DataSet オブジェクト................................................................225 6.3 環境のセットアップ................................................................................................227 6.3.1 IBM Database Add-Ins for Visual Studio......................................................228 6.3.2 DB2 と Visual Studio の使用.........................................................................230 6.4 .NET による DB2 アプリケーションの開発 ..............................................................235 6.4.1 IBM Data Server Provider for .NET による DB2 データベース接続................237 6.4.2 OLE DB .NET Data Provider による DB2 データベース接続..........................239 6.5 .NET を使ったデータの操作.................................................................................244 6.5.1 サンプルプログラムのビルドと実行 ..................................................................245 6.6 演習 ....................................................................................................................245 6.7 まとめ ..................................................................................................................246 6.8 確認問題 .............................................................................................................246 第 7 章 Ruby on Rails によるアプリケーション開発..........................................................249 7.1 DB2 と稼働する Ruby on Rails アプリケーション:概要...........................................249 7.2 RoR 環境のセットアップ........................................................................................252 7.2.1 Ruby の導入 ................................................................................................252 7.2.2 Rails の導入 .................................................................................................256 7.2.3 RoR アプリケーションの作成と Web サーバーの起動......................................257 7.2.4 DB2 データベースを使う:ibm_db gem ..........................................................259 7.3 RoR アプリケーションの開発.................................................................................263 7.3.1 サンプルアプリケーションの開発:書籍カタログ ................................................264 7.3.2 レイアウトのカスタマイズ .................................................................................276 7.4 演習問題 .............................................................................................................282 7.5 まとめ ..................................................................................................................283 7.6 確認問題 .............................................................................................................283 第 8 章 – PHP によるアプリケーション開発 .......................................................................285 8.2.1.2 Windows 上での PHP 環境の構築 .............................................................288 8.3 PHP-DB2 アプリケーション開発 ............................................................................289 8.3.1 DB2 で使える PHP 拡張................................................................................289 8.3.2 ibm_db2 拡張を使った PHP アプリケーション開発 ..........................................289 8.3.3 PDO_IBM/PDO_ODBC を使った PHP 開発..................................................300 8.4 PHP と DB2 の最適化 ..........................................................................................317 8.4.1 PHP-DB2 でパフォーマンスを向上するデザイン上の考慮点............................317 8.5 演習 ....................................................................................................................317 11 8.6 まとめ ................................................................................................................. 318 8.7 確認問題 ............................................................................................................ 318 第 9 章 Perl によるアプリケーション開発.......................................................................... 321 9.1 Perl – DB2 間のアプリケーション:全体像 ............................................................ 321 9.2 環境設定 ............................................................................................................ 323 9.2.1 Perl アダプターとドライバー........................................................................... 324 9.3 Perl DB2 アプリケーションの開発 ......................................................................... 325 9.3.1 DB2 データベースへの接続.......................................................................... 325 9.3.2 データの抽出................................................................................................... 327 9.3.3 データの挿入・更新・削除 ............................................................................. 328 9.3.4 パラメーター・マーカーでの SQL ステートメント実行........................................ 330 9.3.5 ストアード・プロシージャー・コール ................................................................. 332 9.4 演習 ................................................................................................................... 334 9.5 まとめ ................................................................................................................. 336 9.6 確認問題 ............................................................................................................ 336 第 10 章:Python によるアプリケーション開発.................................................................. 339 10.1 Python – DB2 アプリケーション:概要 ................................................................. 339 10.1.1 IBM が定義している API と ibm_db ドライバー ............................................. 340 10.1.2 Python Database API と ibm_db_dbi ドライバー ......................................... 340 10.1.3 SQLAlchemy と ibm_db_sa アダプター ...................................................... 341 10.1.4 Django フレームワークと ibm_db_django アダプター ................................... 341 10.2 環境のセットアップ............................................................................................. 341 10.2.1 Python アダプターとドライバー.................................................................... 342 10.3 Python DB2 アプリケーションの開発 .................................................................. 349 10.3.1 DB2 データベースへの接続........................................................................ 349 10.3.2 データの読み出し....................................................................................... 350 10.3.3 データの挿入、更新、削除 .......................................................................... 353 10.3.4 パラメーター・マーカーを含んだ SQL の実行 ............................................... 354 10.3.5 ストアード・プロシージャーの呼び出し .......................................................... 357 10.4 課題 ................................................................................................................. 359 10.5 まとめ ............................................................................................................... 360 10.6 練習問題 .......................................................................................................... 360 付録 A – 確認問題の解答.............................................................................................. 363 付録 B – トラブルシューティング ..................................................................................... 371 B.1 エラー・コードに関しての詳細の確認.................................................................... 372 B.2 SQLCODE と SQLSTATE ................................................................................. 372 B.3 DB2 管理通知ログ .............................................................................................. 373 B.4 db2diag.log ....................................................................................................... 373 B.5 CLI トレース........................................................................................................ 374 B.6 DB2 の障害と修正.............................................................................................. 374 参考文献 ....................................................................................................................... 375 関連情報 ....................................................................................................................... 375 Web サイト................................................................................................................ 375 本 ............................................................................................................................ 376 12 DB2 アプリケーション開発入門 コンタクト先のメールアドレス........................................................................................377 はじめに 今日の社会において、最新のスキルを保つことは非常に困難になってきています。非常に多くの 新しいテクノロジーが開発され、それらを学ぶ時間は削減される傾向にあります。DB2® キャンパ ス・ブック・シリーズは最小限の時間と努力で最新のテクノロジーの多くを学ぶことができるように開 発されています。 本書の対象読者 本書はデータベース・アプリケーション開発に携わるあらゆる方を対象としています。アプリケーショ ン開発者、コンサルタント、ソフトウェア・アーキテクト、インストラクター、学生などすべての方が対 象となります。データベース管理者(DBA)やプロダクト・マネージャーにとっても有益な参考書とな るでしょう。 本書の構成内容 本書は、おなじ eBook シリーズの DB2 Express-C 入門 におけるアプリケーション開発の章を掘 り下げて一冊の書籍にまとめています。実際、第1章と第2章は先の入門書のアプリケーション開 発の章を詳細化しています。また、第3章はストアード・プロシージャーやユーザー定義関数につ いてご説明していますが、これは eBook シリーズの Getting Started with IBM Data Studio for DB2 に深く関係しています。第4章以降は Java TM、 C/C++、 .NET、 Ruby on Rail、 PHP、 Perl、 および Python など、それぞれのプログラミング言語を使ったクライアント・サイド・プログラミングに ついてご説明しています。 ほぼ全ての章には演習があります。演習に必要なファイルは本書と共に提供されている 以下の zip ファイルに含まれています。 Exercise_Files_DB2_Application_Development.zip コミュニティーのためのガイド 本書はさまざまなコミュニティーの協力により作成されています。コミュニティーは大学の教授や学 生のほか、IBM 社員を含むプロフェッショナルによって構成されています。本書はそれらのコミュニ ティーに対して無償で提供されています。多くのコミュニティー・メンバーが本書の開発に携わり、 そしてコミュニティーにより複数の言語に翻訳されています。本書に関するフィードバック、新しい 教材の提供、既存の教材の改善、または 他の言語への翻訳でご協 力いただける場合は、 「Getting Started with DB2 Application Development book feedback」という件名で、本文に英 語で内容を記載した E メールを [email protected] まで送付願います。 表記について 本書では、コマンド、SQL ステートメント、プログラム・コードのサンプルを紹介しています。特定の キーワードは大文字の太字で記述しています。例えば、「NULL は値が不定な状態を意味してい ます。」のように使われます。コマンドは小文字の太字で記述しています。例えば、「dir コマンドは 14 DB2 アプリケーション開発入門 Windows® プラットフォームにおいて、ファイルやサブ・ディレクトリーの一覧を表示するコマンドで す。」のように使われます。SQL ステートメントは大文字の太字で記述しています。例えば、 「SELECT ステートメントは表から情報を読み出す際に使用します。」のように使われます。 対象となるものを示す際は太字のイタリックで記述しています。例えば、「flights 表には5つのカラ ムがあります。」のように使われます。 イタリックは、コマンドやステートメントの構文における変数名としても使用されます。変数名が複数 の英単語から 構成される場合 は、下線でつながれ表現し ます。例 えば「 CREATE TABLE table_name」のように使われます。 さらに詳しく学ぶには 本書を学ばれた方は、eBook シリーズの以下の書籍を参照して、本書の各章でご紹介している内 容に関して詳細を学ばれることをお勧めします。 Getting started with DB2 Express-C (日本語版: DB2 Express-C 入門) Getting started with IBM Data Studio for DB2 Getting started with Java Getting started with C/C++ Getting started with .NET Getting started with Ruby on Rails Getting started with PHP Getting started with Perl Getting started with Python Getting started with Open source development Getting started with Eclipse 以下の図は、DB2 on Campus の eBook シリーズ一覧の体系を示しています。すべての eBook は http://ibm.com/db2/books からダウンロード可能です。 15 The DB2 on Campus book series 著者 Raul F. Chong は DB2 on Campus のプログラム・マネージャーで、IBM トロント研究所の DB2 テクニカル・エバンジェリストです。彼の主な業務は DB2 のコミュニティーを世界に広めることにあ ります。彼は 1997 に IBM に入社し、社内でさまざまな業務を担当しました。彼は DB2 コンサルタ ントとして、他社リレーショナル・データベースから DB2 への移行プロジェクトで IBM のビジネス・ パートナーを支援しました。また、彼は DB2 の技術支援のスペシャリストとして OS/390®、z/OS®、 Linux®、UNIX® および Windows® プラットフォーム上でのさまざまな DB2 の問題解決を支援し ました。さらに彼は数多くの DB2 ワークショップで講師を担当し、多くの書籍を著作し、また、DB2 認定試験の指導書の作成にも貢献しています。彼の書籍の1つである Understanding DB2 Learning Visually with Examples 2nd Edition (ISBN-10: 0131580183) の中で、彼は何年にも 及ぶ DB2 のさまざまな経験をまとめています。彼はさらに DB2 SQL PL Essential Guide for DB2 UDB on Linux, UNIX, Windows, i5/OS, and z/OS (ISBN 0131477005) の共著者でもあり、 DB2 on Campus 書籍シリーズにおいてはプロジェクト・リーダーを担当するとともに多くの書籍の 共著者となっています。 Xiqiang Ji は IBM アジア・パシフィック地域の DB2 レベル2サポート・チームに所属している、 DB2 アドバンスド・サポート・エンジニアで、シドニーに在住しています。彼の任務は、IBM アジア・ パシフィック地域および全世界のお客様に対してさまざまな DB2 の問題解決に支援することにあ ります。過去5年間、彼はさまざまな業界で DB2 を利用されているお客様に対して、多くの重要障 害を解決してきました。それ以前は、IBM ソフトウェア・グループのテクニカル・コンサルタントとして 5年間従事し、IBM のビジネス・パートナーや独立系ソフトウェア・ベンダー(ISV)の DB2 アプリケ ーション開発や DB2 ビジネス・インテリジェンス・ソリューションの構築を支援してきました。 Priyanka Joshi は IBM アジア・パシフィック地域の DB2 レベル2サポート・チームに所属してい る、DB2 アドバンスド・サポート・エンジニアで、IBM インド・ソフトウェア研究所に在籍しています。 彼女の任務は、Linux®、UNIX® および Windows (LUW) 版 DB2 に対するテクニカル・サポート を提供することにあります。彼女は 2006 年に IBM に入社し DB2 LUW に関する多くのプリ・セー ルス、ポスト・セールスに貢献してきました。彼女の専門は DB2 コモン・クライアント・テクノロジーで、 DB2 プロフェッショ ナルに認定されて います。彼女は IBM が展開するナレッジ・サポー ト (Knowledge Centered Support, KCS)のアジア・パシフィック地域におけるナレッジ・チャンピオン として認められています。また、IBM の名誉あるテクニカル・リーダーの一人でもあり、複数の IBM 製品チームと協業し、IBM のお客様に対して洗練されたソリューションを提供しています。 Vineet Mishra は IBM インド・ソフトウェア研究所に在籍しているソフトウェア・エンジニアで DB2 LUW チームとともに働いています。彼は 2007 年に IBM に入社した C/C++ 言語のスペシャリスト です。彼の専門分野は HADR、ストアード・プロシージャーおよびユーザー定義関数、組み込み SQL、そして OS カーネルです。彼は IBM アカデミック・イニシアティブおよび IBM ユニバーシテ ィ・リレーションシップのメンバーで DB2 (LUW) のノウハウを広く公開してきています。彼は DB2 フォーラムでも回答者として活躍しています。 Min Wei Yao は主にビジネス・インテリジェンスに取り組んでいるアプリケーション開発者です。彼 は 2008 年に IBM に入社後、IBM グローバル・ビジネス・サービスに所属しています。彼は開発 者として働くだけでなく、Linux 版 DB2 の評価・検証にも取り組んでいます。彼は IBM 認定の DB2 アプリケーション開発者であり、管理者でもあります。 18 DB2 アプリケーション開発入門 貢献者 本書の執筆に際し、編集、レビュー、資料提供等で貢献された方々を以下にご紹介します。 貢献者 会社/大学 職業 貢献内容 Antonio Cangiano IBM トロント研究所 Software Engineer and Technical Evangelist テクニカル・レビュ ーの一部 Praveen Devarao IBM インド・ソフトウェ ア研究所 Software Engineer, IBM Opensource Technologies for IBM Data Servers テクニカル・レビュ ーの一部 Vinay B. Ganapavarapu ニューメキシコが医学 学生 テクニカル・レビュ ーの一部 Upal Hossain IBM トロント研究所 Software Developer, DB2 Information Development Infrastructure テクニカル・レビュ ーの一部 Leon Katsnelson IBM トロント研究所 Program Director, IBM Data Servers テクニカル・レビュ ー Anil Mahadev IDUG インド IDUG India chairman, database consultant テクニカル・レビュ ーの一部 Rahul Priyadashi IBM インド・ソフトウェ ア研究所 System Software Engineer, IBM open source Technologies for IBM Data Servers テクニカル・レビュ ーの一部 謝辞 本書作成にあたり、以下の方々のご協力に感謝いたします。 Natasha Tolub … 本書の表紙デザイン Susan Visser … 本書の出版に関する支援 19 訳者、監訳者 本書の日本語版は、日本アイ・ビー・エム(株)システム・テクニカル・サービス・センタ ーに所属するメンバーにより作成されました。 監訳者 川瀬 智 (Satoshi Kawase) … Advisory Software Engineer, DB2 Level2 Support & Integrated Data Management Technologies (IDMT) Technical Support, Software Group 安藤 亮一 (Ryoichi Ando) …IT Specialist, IM Technical Support #1, Global Technology Services 訳者 稲垣 巌 (Iwao Inagaki) …Senior Manager - Software Engineering, AP IDMT & Japan Technical Support #2, Software Group 中山 智絵 (Chie Nakayama) …Advisory IT Specialist, IM Technical Support #1, Global Technology Services 小林 晃裕 (Akihiro Kobayashi) …Advisory IT Specialist, DB2 Technical Support, Software Group 小田 実 (Makoto Oda) …Advisory Software Engineer, DB2 Level 2 support, Software Group 西田 寛 (Hiroshi Nishida) …Advisory IT Specialist, IM Technical Support #1, Global Technology Services 岩井 麻子 (Asako Iwai) …Advisory IT Specialist, Discovery Level2 Support, ECM Technical support, Software Group 定近 昌人 (Masato Sadachika) …IT Specialist, IM Products Level 1 support, Software Technical Support, Global Technology Services 本橋 貴司 (Takashi Motohashi) …Manager - Senior ITS, IM Technical Support #1, Global Technology Services 1 第1章 DB2 アプリケーション開発の概要 IBM® DB2® はリレーショナル・データおよび XML データの両方を管理できる強力なデータ・サ ーバー・ソフトウェアです。本製品はデータベースの管理者だけでなく、データベースの開発者に とっても柔軟性のある機能を提供しています。どのプログラミング言語を使う場合であっても、DB2 はデータベース・アプリケーションの開発に必要なドライバーやアダプター、拡張機能を提供して います。さらに、DB2 Express-C は無償で使用可能な DB2 のエディションで、データベース容量 に制限なく、ほかのバージョンの DB2 と同等のプログラミング言語を使用することが可能です。 DB2 Express-C を使って開発を行えば、アプリケーションを変更することなく DB2 のあらゆるエデ ィションで実行することが可能です。 本章では、以下の点をご説明します。 ストアード・プロシージャーとユーザー定義関数を使ったサーバー・サイド・プログラミング その他のプログラミング言語を使ったクライアント・サイド・プログラミング 1.1 DB2 アプリケーション開発 : 全体像 DB2 は、ストアード・プロシージャーやユーザー定義関数などのサーバー・サイドの開発のための 柔軟性ある環境をデータベース開発者に提供します。さらに、アプリケーション開発者は任意のプ ログラミング言語でクライアント・アプリケーション開発を行うことが可能です。 22 DB2 アプリケーション開発入門 図 1.1 - DB2 データベースおよびアプリケーション開発の全体像 図 1.1 の左側は、アプリケーション・プログラマーが開発やテストを行うためのクライアント環境を示 しています。このクライアント環境では、通常、オペレーティング・システム上に IBM データ・サーバ ー・クライアントをインストールして開発を行います。IBM データ・サーバー・クライアントには JDBC ドライバーや ODBC/CLI ドライバーなど、データベース接続に必要なドライバーが含まれています。 これらのドライバーは IBM DB2 Express-C の Web サイト ( http://ibm.com/db2/express ) から 個別にダウンロードすることも可能です。 IBM Data Studio、 InfoSphere™ Data Architect (IDA)、 Rational® Software Architect (RSA)、 Rational Application Developer (RAD) などのプログラミング・ツールがあれば、任意のプログラミ ング言語でアプリケーション開発を行うことができます。各種プログラミング言語に必要な API ライ ブラリーも IBM データ・サーバー・クライアントとともに同梱されています。そのため、これだけで DB2 サーバーに接続し、あらゆるプログラミング言語の API を使用して SQL や XQuery が DB2 側で処理される環境が整います。表 1.1 は前述のツールに関する概要をまとめています。 Tool name Description ツール名称 説明 IBM Data Studio IBM Data Studio は Eclipse ベースの無償の ツールで、データ・サーバーの管理やストアー ド・プロシージャー、ユーザー定義関数、Data Web サ ー ビ ス の 開 発 が 可 能 で す 。 詳 細 は eBook Getting started with IBM Data Studio for DB2. をご参照ください。 第1章 DB2 アプリケーション開発の概要 23 InfoSphere Data Architect (IDA) IDA はデータ・モデリングのツールです。デー タベースの論理設計、物理設計の作業の際に 使われます。 Rational Software Architect (RSA) RSA は Eclipse ベースのツールで、UML モデ ルを使った分析・設計から開発までをサポート するモデル駆動型開発環境を提供します。 Rational Application Developer (RAD) RAD は Eclipse ベースのツールで、ソフトウェ ア開発者向けのアプリケーション開発環境を提 供します。 Visual Studio Microsoft® Visual Studio は、Windows® プラ ットフォーム上で Microsoft のテクノロジーを使 ったアプリケーション開発を行うための統合環 境 (IDE) です。 ZendCore ZendCore は、かつて ZendCore for IBM と呼 ばれていたもので、PHP アプリケーション開発 のための無償の統合環境 (IDE) です。 表 1.1 – DB2 アプリケーション開発で使用するツール 図 1.1 の右側は、1つのデータベースを含む DB2 サーバーを示しています。このデータベースに は、ストアード・プロシージャーやユーザー定義関数、トリガーが含まれています。これらのオブジェ クトについては、後の章で詳しくご説明します。 特筆すべきことに、DB2 は、IBM Development and Test Cloud だけでなく、 Amazon クラウド上 にも DB2 を提供しています。個人や企業が開発環境、本番環境に必要なサーバーを手配するた めの予算が十分でないようなときは、クラウドはその代替案として利用可能です。必要な時間だけ クラウド上の資源を借りることができます。クラウド上の DB2 の利用料金体系などは後の章で詳しく ご説明します。 1.2 サーバー・サイドのアプリケーション開発 DB2 におけるサーバー・サイドのアプリケーション開発とは、データベース・アプリケーションを開発 して DB2 に格納することです。この節では以下のデータベース・アプリケーションについて簡単に ご説明します。 ストアード・プロシージャー ユーザー定義関数 (UDF) トリガー 24 DB2 アプリケーション開発入門 1.2.1 ストアード・プロシージャー ストアード・プロシージャーは、SQL ステートメントやビジネス・ロジックを含んだデータベース・アプ リケーション・オブジェクトです。アプリケーション・ロジックの一部をデータベース側に保持すること で、アプリケーションとデータベース間のネットワーク・トラフィックが削減し、パフォーマンスを向上 させることが可能です。さらに、ストアード・プロシージャーはサーバー上で一括管理されるため、ほ かのアプリケーションが同じストアード・プロシージャーを再利用することも可能です。ストアード・プ ロシージャーを呼び出すには call ステートメントを使用します。DB2 は、SQL PL、PL/SQL、Java、 C/C++、CLR、OLE、COBOL など、さまざまな言語でストアード・プロシージャーを開発することが 可能です。DB2 コマンド・ウィンドウや Linux® シェルを使って SQL PL ストアード・プロシージャー を作成し、呼び出す簡単な例を以下に示します。 db2 create procedure P1 begin end db2 call P1 この例で作成されたストアード・プロシージャー P1 は、実際には何もしない空のストアード・プロシ ージャーです。ここでは、容易にストアード・プロシージャーを作成することができることを示してい ます。複雑なロジックを持ったストアード・プロシージャーを開発するには、デバッガー機能を持っ た IBM Data Studio を使うことをお勧めします。 1.2.2 ユーザー定義関数 (UDF) ユーザー定義関数(UDF) は、SQL 言語にユーザー独自のロジックを組み込むためのデータベー ス・アプリケーション・オブジェクトです。ユーザー定義関数は、関数内で定義されたビジネス・ロジ ックにしたがって、基本的には常に1つもしくは複数の値を返します。ユーザー定義関数は、SQL ステートメント中に含めて使用するか、values 関数を使って呼び出すことが可能です。 DB2 は、 SQL PL、PL/SQL、Java、C/C++、OLE DB、CLR などを使用してユーザー定義関数を開発する ことが可能です。 DB2 コマンド・ウィンドウや Linux シェルを使って SQL PL ユーザー定義関数を作成し、呼び出 す簡単な例を以下に示します。 db2 create function F1() returns integer begin return 1000; end db2 values F1 ここでは、常に integer 型の値 1000 を返す関数 F1 を定義し、VALUES ステートメントによりこの 関数を呼び出しています。ストアード・プロシージャー同様、ユーザー定義関数の開発には IBM Data Studio を使用されることをお勧めします。 第1章 DB2 アプリケーション開発の概要 25 1.2.3 トリガー トリガーは、表やビュー上の操作を自動的に実行するためのオブジェクトです。トリガーが定義され たオブジェクト上でトリガー・アクションが実行されると、トリガーが起動されます。トリガーは通常、ア プリケーション・オブジェクトとして扱われていないため、トリガーのコーディングは、通常、データベ ース開発者ではなく、データベース管理者が行っています。いずれにせよトリガーは多少のコーデ ィングが必要となるため、本書ではトリガーをこの節で扱っています。以下にトリガーの例を示しま す。 create trigger myvalidate no cascade before insert on T1 referencing NEW as N for each row begin atomic set (N.myxmlcol) = XMLVALIDATE(N.myxmlcol according to xmlschema id myxmlschema); end この例では、トリガーは表 T1 上の INSERT が行われる前に起動されます。このトリガーは値 (XML 文書)をセットしますが、その際に XMLVALIDATE 関数が呼び出され、指定されたスキー マで XML 文書の妥当性検査が行われます。XML および XML スキーマについては、 第2章 DB2 pureXML でとりあげます。 1.3 クライアント・サイドのアプリケーション開発 クライアント・サイドのアプリケーション開発とは、その名のとおり、クライアント側でプログラムをコー ディングし、API を使って DB2 データベースにアクセスするアプリケーションの開発をさします。 DB2 にアクセスするための API は DB2 が提供しています。この節では、以下の内容をご説明し ます。 組み込み SQL 静的 SQL および動的 SQL CLI および ODBC JDBC、SQLJ、pureQuery OLE DB ADO.NET PHP Ruby on Rails Perl Python 26 DB2 アプリケーション開発入門 1.3.1 組み込み SQL 組み込み SQL アプリケーション は C、C++、COBOL などのホスト言語に SQL が埋め込まれて いるアプリケーションをさします。組み込み SQL アプリケーションは静的 SQL もしくは動的 SQL を含めることが可能です。詳細は次章でご説明します。図 1.2 は組み込み SQL のビルドの流れを 示しています。 図 1.2 – 組み込み SQL アプリケーションのビルドの流れ この図において、hello.sqc という C 言語プログラムは組み込み SQL を含んでいます。C 言語用 の埋め込み SQL では、図 1.2 の赤丸で示された EXEC SQL を使い、プリコンパイルの際に組み 込 み SQL と 実 際 の C 言 語 の コ ー ド に 分 割 し ま す 。 ま た 、 hello.sqc に あ る と お り 、 変 数 は :dbname、 :userID、:psw などのようにコロンで始まります。これらは、ホスト変数と言います。 ホスト変数はホスト言語上で定義され、組み込み SQL ステートメントの中で参照されます。 precompile コマンド(もしくは prep コマンド)を bindfile オプションつきで実行すると、SQL ステ ートメントだけを含む hello.bnd と C 言語のコードだけが含まれる hello.c との2つのファイルが生 成されます。バインド・ファイルは bind コマンドを使ってコンパイルされ、データベースに格納する パッケージを作成します。パッケージはコンパイルされた実行可能な SQL およびアクセス・パスを 含み、DB2 はそれらの情報に従ってデータを処理します。bind コマンドを実行する際には、デー タベースへの接続が必要です。図の下側は、通常の C プログラム同様、 hello.c ファイルがコンパ イルおよびリンクされる流れを示しています。最終的に hello.exe がデータベースに格納されたパ ッケージと照合され、正しく実行されます。 第1章 DB2 アプリケーション開発の概要 27 1.3.2 静的 SQL と動的 SQL 静的 SQL ステートメントはプリコンパイルの時点で SQL の構造が明確になっているものをいいま す。例えば以下のようなものです。 SELECT lastname, salary FROM employee この例では、ステートメントが参照している列(lastname、salary)や表(employee)はプリコンパ イルの段階で確定しています。以下の例も静的 SQL ステートメントです。 SELECT lastname, salary FROM employee WHERE firstnme = :fname 2番目の例では、ホスト変数 :fname は埋め込み SQL ステートメントの一部として使用されます。 ホスト変数の値は実行時まで不確定ですが、データの型は明確で、列名や表名などのオブジェク トも事前に明確です。そのため、この例も1番目と同様に静的 SQL として扱われます。 静的に実行される SQL ステートメントは、アプリケーションの実行前にプリコンパイル、バインド、お よびコンパイルが行われます。静的 SQL は、統計情報が変わらないデータベースで使用するの がベストです。もう1つの事例を見てみましょう。 SELECT ?, ? FROM ? この例では、このステートメントで参照される列名や表名は実行時まで確定しません。そのため、ア クセス・プランは実行時に計算され、その時点での統計情報が使用されます。このようなステートメ ントは動的 SQL ステートメントして扱われます。 JDBC や ODBC といったいくつかのプログラミング API では、SQL ステートメントの型が確定して いるかにかかわらず、常に動的 SQL が使用されます。例えば、SELECT lastname, salary FROM employee というステートメントはすべての列名や表名は事前に確定していますが、JDBC や ODBC を経由する際はステートメントのプリコンパイルは行われません。このステートメントに対 するすべてのアクセス・プランは実行時に計算されます。 一般に、SQL ステートメントを動的に扱うためには以下の2つのステートメントが使用されます。 PREPARE: このステートメントは、 SQL ステートメントの事前準備およびコンパイルを行い、 データを取得する際のアクセス・プランを算出します。 EXECUTE: このステートメントは、SQL の実行を行います。 これ以外に、PREPARE と EXECUTE を同時に行う EXECUTE IMMEDIATELY というステート メントがあります。 リスト 1.1 は C 言語における組み込みの動的 SQL で事前準備および実行を行っている例を示し ています。 strcpy(hVStmtDyn, “SELECT name FROM emp WHERE dept = ?"); PREPARE StmtDyn FROM :hVStmtDyn; EXECUTE StmtDyn USING 1; EXECUTE StmtDyn USING 2; 28 DB2 アプリケーション開発入門 リスト 1.1 – C 言語での組み込みの動的 SQL における PREPARE と EXECUTE の例 リスト 1.2 は、リスト 1.1 と同じ内容を EXECUTE IMMEDIATELY ステートメントを使って記述した 例です。 EXECUTE IMMEDIATELY SELECT name from EMP where dept = 1 EXECUTE IMMEDIATELY SELECT name from EMP where dept = 2 リスト 1.2 – C 言語での組み込みの動的 SQL における EXECUTE IMMEDIATELY の例 PHP、Ruby on Rails など、多くの動的プログラミング言語では、SQL は動的に実行されます。こ のような言語においては、プログラマーは同一 SQL ステートメントに異なる値をセットするようなコ ードを記述することがあります。以下に例を示します。 SELECT lastname, salary FROM employee where firstnme = 'Raul' SELECT lastname, salary FROM employee where firstnme = 'Jin' ... この例では、firstnme 列の値を除いてステートメントは同一のものです。DB2 では、これらの2つ の動的 SQL ステートメントは別のものと解釈し、実行時にはそれぞれのステートメントに対して個 別に事前準備と実行が行われます。同一のステートメントに対して事前準備が複数回行われると、 そのオーバーヘッドはパフォーマンス劣化の要因となります。そのため、DB2 9.7 以前の環境では、 ステートメントを以下のように記述することをお勧めします。 SELECT lastname, salary FROM employee where firstnme = ? ステートメントで使用されている疑問符(?) は、パラメーター・マーカーといいます。パラメーター・マ ーカーを使うことで、プログラムはステートメントの事前準備を1回に抑えることが可能です。その後、 パラメーター・マーカーに対して異なる値をセットしながら複数回の EXECUTE を実行することが 可能になります。 DB2 9.7 からステートメント・コンセントレーターという仕組みが導入されました。これにより、セットさ れる値を除く部分が同一のステートメントは、自動的にパラメーター・マーカーを使った1つのステ ートメントにまとめられるようになりました。その際、EXECUTE ステートメントは異なる値に対して実 行されます。 パフォーマンスに関して言えば、静的 SQL は実行時ではなく事前準備の段階でアクセス・プラン が処理されるため、通常、動的 SQL より高いパフォーマンスが得られます。しかしながら、 INSERT や DELETE などの処理が頻繁に行われる環境においては、事前準備の段階で算出さ れた統計情報は実行時と大きく異なる可能性があるため、静的 SQL は最適な選択とはいえない 場合があります。このようなケースにおいては、動的 SQL がよりよい選択となりうるでしょう。もちろ ん、RUNSTATS によって統計情報が頻繁に更新されていることが前提です。 第1章 DB2 アプリケーション開発の概要 29 注: 組み込み SQL は静的のみと考えている人がいますが、実際には動的、静的の両方があります。 1.3.3 CLI と ODBC コール・レベル・インターフェース (CLI) は、元々 X/Open Company および SQL Access Group により開発されました。これは、RDBMS ベンダーに依存しない、移植可能な C/C++ アプリケーシ ョンの開発のための呼び出し可能 SQL インターフェースの仕様として生まれました。X/Open コー ル・レベル・インターフェースの素案を元に、マイクロソフトは Open Database Connectivity (ODBC) を開発し、その後、ISO CLI 国際標準がほとんどの X/Open コール・レベル・インターフ ェース仕様を認定しました。DB2 CLI は図 1.3 に示すとおり ODBC と SQL/CLI の国際標準の 両方に基づいています。 Figure 1.3 – ODBC と ISO CLI 国際標準に準拠した DB2 CLI DB2 CLI は ODBC 3.51 に準拠しており、ODBC ドライバー・マネージャーがロードする ODBC ドライバーとして使用することが可能です。 図 1.4 - ODBC 3.51 準拠の DB2 CLI CLI/ODBC には以下の特徴があります。 30 DB2 アプリケーション開発入門 RDBMS ベンダー間のコード移植性が高い 組み込み SQL と異なり、プリコンパイラーやホスト変数の準備が不要 動的 SQL として実行される 広く一般に利用されている CLI/ODBC アプリケーションの実行 に必要なものは DB2 CLI ドライバーだけです。このドライバ ー は 以 下 の DB2 ク ラ イ ア ン ト に 含 ま れ て お り 、 こ れ ら は IBM のサイト http://www.ibm.com/db2/express から無償でダウンロード可能です。 IBM Data Server Client IBM Data Server Runtime Client IBM Data Server Driver for ODBC and CLI CLI/ODBC アプリケーションの開発 には、DB2 CLI ドライバーに加え、適切なライブラリーが必要 で、それらは IBM Data Server Client のみに含まれています。 DB2 CLI ドライバーを使用したアプリケーション環境をセットアップについて理解を深めるため、以 下に例を示します。図 1.5 は、インドネシア、ブラジルとカナダの3地点に環境を配置した例を示し ています。 図 1.5 - DB2 CLI/ODBC サンプル・シナリオ 第1章 DB2 アプリケーション開発の概要 31 この図は2つのシナリオを表しています。 図の左側にあるインドネシア環境では 、ODBC アプリケーションが稼動しており、それらは Oracle® や Microsoft® SQL Server® 、DB2 などの RDBMS に接続しています。ODBC ドライ バー・マネージャーは接続されるデータベースに合わせた適切な ODBC ドライバーをロードしま す。カナダにある DB2 データベースに接続するアプリケーションは、リモート接続のために DB2 ク ライアントを経由して接続しています。 図の右側では、ブラジルで CLI アプリケーションが稼動しています。ここでは、ODBC では対応で きない特定の機能を使い、また、DB2 以外での使用は想定していないため、CLI アプリケーション を使用しています。この CLI アプリケーションは、DB2 CLI ドライバーを使って DB2 にアクセスし ます。このアプリケーションは、ブラジルにあるローカルの DB2 データベースに接続していますが、 カナダにあるリモートのデータベースに接続する必要がある際には、DB2 クライアント経由します。 この節の終わりに、CLI/ODBC アプリケーションと組み込み SQL を使った C 言語の動的アプリケ ーションの比較をご紹介します。図 1.6 はこれらの比較を図示しています。 図 1.6 - CLI/ODBC アプリケーションと組み込み SQL を使用した C 言語の動的アプリケーション 図 1.6 に示すとおり、CLI/ODBC と組み込み SQL の C 言語動的 SQL の違いは、CLI/IDBC で はコード移植性が高く、接続文字列を変更する程度の簡単な修正で DB2 以外の RDBMS にも 接続できるということです。組み込み SQL を使用した C 言語の動的アプリケーションの場合は、 DB2 固有のコードが必要になります。もちろん、PREPARE や EXECUTE の関数がどのように呼 び出されるかも異なります。 1.3.4 JDBC, SQLJ および pureQuery Java Database Connectivity (JDBC) は Java プログラミング言語の API で、データベースへ のアクセスのための標準です。JDBC は複数の RDBMS ベンダー間における高い移植性を提供 32 DB2 アプリケーション開発入門 しています。変更に必要な箇所は JDBC ドライバーをロードする箇所と、接続文字列程度です。 JDBC は動的 SQL のみを扱います。また、JDBC は広く一般に使用されています。 SQLJ は Java プログラムにおける組み込み SQL のための標準です。主に静的 SQL で使用さ れ、図 1.7 に示すように、JDBC との相互運用が可能です。一般的に JDBC プログラムに比べて コンパクトで高いパフォーマンスが得られることが多いですが、JDBC ほど広く一般には使用され ていません。SQLJ プログラムは、コンパイルの前に SQLJ トランスレーターというプリプロセッサー を実行させる必要があります。 図 1.7 – SQLJ と JDBC アプリケーションの関係 図 1.7 では、JDBC ドライバーのタイプによって、DB2 クライアントを必要とする場合とそうでない 場合があります。詳細はこの節の後半で説明します。 pureQuery は、IBM Eclipse ベースのプラグインで、リレーショナル・データをオブジェクトとして 管理します。pureQuery は 2007 にリリースされた製品で、オブジェクト指向のコードと、リレーショ ナル・データベース・オブジェクトの間のオブジェクト・リレーショナル・マッピング (ORM) を自動生 成することが可能です。Optim Development Studio (ODS) を使って Java プロジェクトを生成し、 DB2 に接続すると、ODS は接続先データベースのすべてのオブジェクトを探索します。ODS の GUI を通して表を選択して pureQuery のコードを生成し、中にあるリレーショナル表のエンティテ ィーを Java のオブジェクトに変換することが可能です。生成されたコードから、関連する SQL ス テートメントを生成したり、ステートメントを隠蔽した Java のオブジェクトを生成したりできます。生 成された Java のオブジェクトおよびそれに含まれる SQL ステートメントは後から変更可能です。 pureQuery を使えば、実行したい SQL を静的もくしは動的に実行し、その場で必要なものを判断 することができます。pureQuery は Java と .NET の両方をサポートしています。 1.3.4.1 JDBC および SQLJ ドライバー 第1章 DB2 アプリケーション開発の概要 33 JDBC ドライバーにはいくつかの種類があり、それぞれタイプ 1, 2, 3, 4 という名称で区別されてい ますが、このうちタイプ 1 とタイプ 3 は広く一般には使用されていないため、DB2 はこれらのタイプ を提供していません。また、タイプ2に関しては後述のとおり2種類のドライバーを提供しております が、1つは非推奨になっています。 表 1.2 に示すとおり、DB2 ではタイプ 2 とタイプ 4 をサポートしています。タイプ 2 ドライバーは 、 データベースへの接続に DB2 クライアントのモジュールを使用するため、ドライバーのほかに DB2 クライアントをインストールする必要があります。タイプ 4 は pure Java のため、DB2 クライア ントは不要ですが、JDBC アプリケーションが実行される環境にドライバーがインストールされる必 要があります。 ドライバ ーのタ イプ ドライバー名 パッケージ サポート・レ ベル 最低限必要な SDK for Java のバージョン タイプ 2 Linux, UNIX® お よ び Windows 用 の DB2 JDBC タイプ 2 ドライバー (非推奨*) db2java.zip JDBC 1.2 お よ び JDBC 2.0 1.4.2 タイプ 2 およ びタイ プ4 IBM Data Server Driver for JDBC and SQLJ db2jcc.jar と sqlj.zip JDBC 準拠 1.4.2 db2jcc4.jar と sqlj4.zip JDBC 4.0 の一部機能 のサポート 3.0 6 表 1.2 - DB2 JDBC および SQLJ ドライバー * 「非推奨」とは、「サポートはされますが、今後の拡張は行われない」ということを意味します。 前述、および表 1.2 にも記載のとおり、タイプ 2 には2つの異なるドライバーが提供されています。 しかしながら、db2java.zip というファイルで提供されている Linux, UNIX および Windows 用の DB2 JDBC タイプ 2 ドライバーは非推奨です。 DB2 サーバー、もしくは DB2 クライアント、IBM Data Server Driver for JDBC and SQLJ のいず れかをインストールすると JDBC 3.0 準拠の db2jcc.jar および sqlj.zip がクラス・パスに自動的に 追加されます。 1.3.5 OLE DB Object Linking and Embedding, Database (OLE DB) は、多様なデータ・ソースにアクセス するためのインターフェースを提供しています。ODBC に置き換わるものとして設計されており、さ らに、オブジェクト指向データベースやスプレッド・シートなどの非リレーショナル・データベースを 34 DB2 アプリケーション開発入門 含む多様なデータ・ソースへのアクセスをサポートしています。OLE DB は Component Object Model (COM) の技術を使って実装されています。 OLE DB コンシューマーは IBM OLE DB Provider for DB2 を使って DB2 データベースにアクセ スすることが可能です。このプロバイダーには以下の特徴があります。 プロバイダー名: IBMDADB2 OLE DB Provider 仕様レベル 0 およびいくつかのレベル 1 インターフェースのサポート Microsoft OLE DB 仕様 V 2.7 およびそれ以降への準拠 前提として IBM Data Server Client および Microsoft Data Access Components (MDAC) がインストールされていること。 IBMDADB2 が 明 示 的 に 指 定 さ れ て い な い と き は 、 Microsoft OLE DB ド ラ イ バ ー (MSDASQL)がデフォルトで使用されます。MSDASQL は、OLE DB を使用しているクラ イアントから ODBC ドライバー経由で Microsotft SQL Server 以外のデータ・ソースに接 続することが可能ですが、OLE DB ドライバーの全機能を保証しているわけではありませ ん。 1.3.6 ADO.NET .NET Framework は、Component Object Model (COM) に置き換わる Microsoft のしくみで す。.NET Framework 上で開発可能なプログラミング言語は 40 以上あり、その中から好きな言語 で .NET アプリケーションを開発することができます。特に有名は言語として C# や Visual Basic .NET などがあげられます。 .NET Framework のクラス・ライブラリーは .NET アプリケーションを開発するためのビルディング・ ブロックを提供しています。このクラス・ライブラリーはプログラミング言語に非依存で、オペレーティ ング・システムやアプリケーション・サービスに対するインターフェースを提供しています。.NET ア プリケーションは、開発言語に関係なく、中間言語 (IL) のバイト・コードにコンパイルされます。 共通言語ランタイム (CLR) は、.NET Framework の基幹部分で、オンザフライで中間コード (IL) へのコンパイルし、実行します。中間コード (IL) の実行中、CLR はオブジェクトの活動化やセキュ リティー・チェック、メモリー割り当て、処理実行から実行後のメモリー開放までを行います。 Java のプログラムは、通常ほとんど、もしくはまったく変更を加えることなく複数のプラットフォーム 上で実行可能です。Java として提供される言語はひとつですが、複数のプラットフォームに対応し ています。それに対し .NET は 40 の言語の中から好きな言語を選んで、唯一のプラットフォーム である Windows 上でほとんど、もしくはまったく変更なしで利用することが可能です。つまり、言語 は複数で、プラットフォームはひとつです。 ADO.NET は、 .NET Framework でデータ・アクセスの仕組みを提供するコンポーネントの集合 体です。ADO.NET は接続型と非接続型の両方のアクセスをサポートしています。非接続型の主 要なコンポーネントはデータ・セット (DataSet) クラスであり、アプリケーションのメモリー内にある データベース・キャッシュとして動作します。 第1章 DB2 アプリケーション開発の概要 35 接続型、非接続型のいずれの場合も、アプリケーションはデータ・プロバイダーと呼ばれるコンポー ネントを介してデータベースにアクセスします。Windows 用の DB2 を含む多くのデータベース製 品は、独自の .NET データ・プロバイダーを提供しています。 .NET データ・プロバイダーは以下の基本的なクラスを実装しています。 Connection : データベース接続を確立し、管理します。 Command : データベースに対して、SQL ステートメントを実行します。 DataReader : データベースから取得した結果セットから情報を読み取ります。 DataAdapter : データ・セットのインスタンスをデータベースにひも付けます。DataAdapter インスタンスを通して、データ・セットはデータベース上のデータを読み取ったり、データベ ース上の表に書き込んだりします。 3 つのプロバイダーの機能は以下の表 1.3 に示す通りです。 データ・プロバイダー ODBC .NET Data Provider 特徴 DB2 CLI ドライバーを使用し、DB2 のデータ・ソースに ODBC 呼び出しを行います。 (非推奨) DB2 CLI ドライバーと同じサポートおよび制約がありま す。 .NET Framework V1.1, 2.0 および 3.0 が利用可能で す。 OLE DB .NET Data Provider IBM DB2 OLE DB ドライバー(IBMDADB2) を使用しま す。 (非推奨) DB2 OLE DB ドライバーと同じサポートおよび制約があ ります。 .NET Framework V1.1, 2.0 および 3.0 が利用可能で す。 DB2 .NET Data Provider ADO.NET インターフェースのサポートを拡張した機能を 提供しています。 (推奨) DB2 用に提供されたプロバイダーで、ADO.NET の標 準と同じクラスおよびメソッドを提供しています。 IBM.DATA.DB2 というネーム・スペースで定義されてい ます。 以下のいずれかをダウンロードすることで導入可能で 36 DB2 アプリケーション開発入門 す。 - Data Server Driver for ODBC, CLI, and .NET - IBM Data Server Runtime Client - DB2 Data Server 表 1.3 - ADO.NET データ・プロバイダー 1.3.7 PHP PHP Hypertext Preprocessor (PHP) はオープン・ソースでプラットフォーム非依存のスクリプト 言語で、Web アプリケーション開発者向けに設計された言語です。HTML の中に埋め込んで使 用することが可能で、通常は Web サーバー上で PHP コードが解釈されたあと、処理結果として Web ページが生成されます。 PHP はモジュラー言語で、拡張モジュールを使用することによって使用できる機能をカスタマイズ できます。データベースへのアクセス機能は主な PHP 拡張機能としてあげられます。 ibm_db2: ibm_db2 拡張モジュールはプロシージャー型のアプリケーション・プログラミン グ・インターフェースで、データベースの作成、読み取り、更新、書き込みのほか、データ ベース・メタデータへの広範なアクセスも行うことができます。このモジュールは PHP 4 ま たは PHP 5 のいずれかでコンパイルできます。 pdo_ibm: pdo_ibm 拡張モジュールは PHP 5.1 で導入された標準オブジェクト指向デ ータベース・インターフェースを通して DB2 データベースへのアクセスを提供している PHP Data Objects (PHO) 拡張モジュールです。このモジュールは DB2 のライブラリー に対してダイレクトにコンパイル可能です。 PHP 拡張モジュールおよびドライバーは PECL のサイト (http://pecl.php.net/ ) から無償でダウン ロード可能です。また、IBM Data Server Client にも含まれています。Ibm_db2 拡張モジュール、 pdo_ibm 拡張モジュールのいずれも IBM DB2 CLI レイヤーを基盤としています。 IBM は Zend 社とのパートナー契約により、ZendCore もサポートしています。ZendCore は、 PHP と DB2 Express-C を使って開発を行うための無償のツールキットです。ZendCore は PHP のライブラリー、Apache Web サーバー、および DB2 Express-C を同梱しています。ZendCore をダウンロードするには、こちら (http://www.ibm.com/software/data/info/zendcore ) をご参照く ださい。 1.3.8 Ruby on Rails Ruby はオープン・ソースのオブジェクト指向型言語です。Rails は Ruby を使用して開発された Web アプリケーション開発のためのフレームワークです。Ruby on Rails (RoR) は、データベース をバックグラウンドに持つ Web ベースのアプリケーション開発のためのフレームワークを提供しま 第1章 DB2 アプリケーション開発の概要 37 す。この新しいホットな技術は、モデル・ビュー・コントローラー (MVC) モデルに基づいており、ア ジャイルなソフトウェア開発を可能にしています。 Rails は特別なファイル・フォーマットや統合開発環境 (IDE) を必要としません。テキスト・エディタ ーだけで始めることが可能です。とはいえ、Rails をサポートした統合環境 (IDE) はいくつか存在 しており、たとえば RadRails があります。これは Eclipse ベースの Rails 環境です。RadRails に 関する詳細はhttp://www.radrails.org/ のサイトをご確認ください。 DB2 は Ruby 1.8.5 以降、および Ruby on Rails 1.2.1 以降をサポートしています。IBM_DB gem は、IBM_DB Ruby ドライバーおよび Rails アダプターが含んでおり、DB2 と組み合わせて 開発を行うことができます。この gem は、IBM Data Server Client と共にインストールする必要が あります。IBM_DB ドライバーおよびアダプターをインストールするには、Ruby gem を使うか、 Rails プラグインとしてインストールすることも可能です。 1.3.9 Perl Perl は広く一般に利用されているインタープリター型プログラミング言語で、多くのオペレーティン グ・システム上で、無償で利用できます。Perl は動的 SQL を使用し、アプリケーションのプロトタイ プを作成するのに適しています。 Perl はデータベース・インターフェース (DBI) と呼ばれる標準モジュールを提供しており、異なる データベースにアクセスすることが可能です。Perl は http://www.perl.com からダウンロードする ことが可能です。Perl は、異なるデータベース・ベンダーのドライバーと通信します。DB2 の場合 は、DBD::DB2 というドライバーがあり、こちら (http://www.ibm.com/software/data/db2/perl. ) か らダウンロード可能です。 1.3.10 Python Python は主にスクリプトに使用される動的言語です。コードの読みやすさを特徴とし、手続き型プ ログラミング、オブジェクト指向プログラミング、アスペクト指向プログラミング、メタプログラミング、関 数型プログラミングなど各種のプログラミング・パラダイムをサポートしています。Python はラピッド・ アプリケーション開発の典型的な例です。 表 1.4 は、Python アプリケーションから DB2 データベースにアクセスするための拡張モジュール を示しています。 拡張モジュール ibm_db 説明 IBM によって定義されたもの 高度な機能を最適な形でサポート SQL 照会の発行、ストアード・プロシージャーの 呼び出し、pureXML の使用に加え、メタデータ 情報へのアクセスも可能 ibm_db_dbi Python Database API Specification v2.0 を 38 DB2 アプリケーション開発入門 実装 ibm_db API でサポートされるいくつかの拡張 機能は非提供 Python Database API Specification v2.0 を サポートするドライバーを備えたアプリケーショ ンが既に存在する場合、簡単に ibm_db に切り 替えることが可能。ibm_db および ibm_db_dbi API は1つのパッケージで提供。 ibm_db_sa オープン・ソースの Python SQL ツールキット で、オブジェクト・リレーショナル・マッパー (ORM) として広く使われている SQLAlchemy をサポート。 表 1.4 - IBM Data Server - Python 拡張モジュール 1.4 XML と DB2 pureXML XML は サービス指向アーキテクチャー(SOA) と共に、Web 2.0 のベースとなる技術です。IBM は早い段階から XML の重要性を認識し、膨大な投資をして pureXML® の技術を提供してきまし た。これは、DB2 に格納された XML 文書を効率よく扱うための技術です。 2006 年に、DB2 9 はハイブリッド・データ・サーバーとして提供されました。これにより、階層型デ ータと共に、リレーショナル・データも格納できるようになりました。それ以前のバージョンの DB2 や、 市場にあるその他のデータ・サーバーでも XML 文書を格納することはできましたが、DB2 9 のデ ータ格納方式はパフォーマンスおよび拡張性により優れたものとなりました。DB2 9 の pureXML 技術により、XML 文書はツリー状に構文解析された形式で内部に保管されるようになりました。そ の結果、XML 文書を扱う処理は格段に高速化しました。その後、DB2 9.5 および DB2 9.7 がリリ ースされ、pureXML の機能はより拡張されました。詳細は 第 15 章 DB2 pureXML をご参照くだ さい。 1.5 Web サービス ここでは少しシンプルな定義として、Web サービスをネットワーク経由で呼び出し可能な関数としま しょう。あなたはその関数がどのプログラミング言語で開発されたかを知る必要はなく、その関数が どのオペレーティング・システムで動作しているかもどこで動作しているかも知る必要がありません。 Web サービスがあれば、XML をベースとした業界標準のプロトコルを使って、アプリケーション間 でデータ交換を行うことができます。図 1.8 に Web サービスの構成例を示します。 第1章 DB2 アプリケーション開発の概要 39 図 1.8 – Web サービスの例 この図において、左側は仮想の航空会社、エアー・アトランティス社としましょう。そこでは Linux 版 の DB2 を使用して、航空機の運行情報を XML フォーマットで格納しています。右側は別の仮想 航空会社、エアー・ディスカバリー社とします。こちらは Windows 上で SQL Server を稼動させ ています。さて、今回、エアー・アトランティス社とエアー・ディスカバリー社はパートナーシップ契約 を結び、お互いのフライト数を調整するために運行情報や価格情報を共有することにしたとしましょ う。両社は異なるオペレーティング・システム (Linux と Windows) をしており、さらにデータベース・ サーバーも異なる (DB2 と SQL Server) ため、情報の共有は容易なことではないでしょう。エア ー・アトランティス社がトロント発北京行のフライト・スケジュールを変更すると、エアー・ディスカバリ ー社はどうしたら彼らが持つ北京発上海行の乗継便のスケジュールを自動的に調整することがで きるでしょうか?答えは Web サービスにあります。エアー・アトランティス社は、DB2 データベース に対してストアード・プロシージャー (例えば getFlightInfo というストアード・プロシージャー) の出 力結果を返すようなデータ Web サービスを開発し、公開することができるでしょう。データ Web サ ー ビ ス と は 、 デ ー タ ベ ー ス の 情 報 を 扱 う Web サ ー ビ ス で す 。 デ ー タ Web サ ー ビ ス が WebSphere Application Server などのアプリケーション・サーバーにデプロイされると、顧客やエ アー・ディスカバリー社などのパートナーは、エアー・アトランティス社のフライト情報をブラウザーか ら簡単にアクセスすることができます。この例では、エアー・アトランティス社は Web サービスの提 供者として振る舞い、Web サービスを開発し、公開しています。一方、エアー・ディスカバリー社は Web サービスの利用者として振る舞い、この Web サービスを利用しています。 40 DB2 アプリケーション開発入門 さらに、エアー・ディスカバリー社は、自社の JDBC アプリケーションからも Web サービスを呼び 出すことができ、SQL Server のデータに対して変更を加えることも可能です。例えば、トロント発 北京行のフライトが平均 12 時間所要するようであれば、エアー・ディスカバリー社は、エアー・アト ランティス社の便がトロントを発つ時刻に飛行時間と乗り継ぎのための時間を追加して北京発上海 行の乗継便の出発時刻を計算することが可能です。乗り継ぎにかかる時間はエアー・ディスカバリ ー社のシステムにあるでしょうから、計算式は以下のようになります。 エアー・アトランティス社が出航時刻を変更すると、エアー・ディスカバリー社がこの Web サービス を呼び出した際に自動的に変更が通知されます。 1.6 管理 API DB2 は多くの管理 API を提供しており、独自のユーティリティーやツールを開発することが可能に なっています。例えば、sqlecrea API を呼び出すことでデータベースを作成することが可能です。 インスタンスを開始するには db2InstanceStart API を使用し、テーブルにデータをインポートす るには db2Import API を使用します。API の一覧は DB2 インフォメーション・センターにあります。 DB2 インフォメーション・センターの URL は関連情報の章をご参照ください。 1.7 開発ツール Microsoft Visual Studio と Eclipse は広く普及している統合開発環境 (IDE) です。どちらの IDE も DB2 を使った開発が可能です。 DB2 ユーザーの中には、MS Excel や MS Access などのサード・パーティ製品と連携して、シン プルなフォームから DB2 に接続するような場合もあるでしょう。この章では、これらの製品と DB2 Excpress-C をどのように組み合わせて使うかをご説明します。 DB2 Express-C は Mac OS X 上でも使用可能ですので、Mac 上で DB2 を動かし、データベー ス・アプリケーションを開発することも可能です。このことは Mac プラットフォームを支持している RoR コミュニティーに対する大きな魅力となるでしょう。 1.7.1 Visual Studio Microsoft Visual Studio での開発用に、DB2 は IBM Database Add-ins for Visual Studio を提 供しています。この無償のアドインをインストールすることで、Visual Studio に DB2 のツールを統 合させることが可能です。このアドインを使えば、開発者は DB2 のデータベースを使う際に別のツ ールに切り替えることなく作業を継続できます。このアドインは、DB2 Express-C の Web サイト (http://ibm.com/db2/express ) からダウンロード可能です。詳細は 第 6 章 .NET によるアプリケ ーション開発 をご参照ください。 第1章 DB2 アプリケーション開発の概要 41 1.7.2 Eclipse Eclipse に関して言えば、IBM は IBM Data Studio という無償の Eclipse ベースのツールを提供 しており、DB2 のインスタンスやデータベースを管理することが可能で。さらに SQL や XQuery、 ストアード・プロシージャー、ユーザー定義関数、データ Web サービスを開発することも可能です。 IBM Data Studio は Eclipse ベースの開発環境ですので、多くの開発者が Eclipse の経験を活 かして作業を進めることが可能です。 IBM Data Studio に関する詳細は、eBook Getting started with IBM Data Studio for DB2 をご 参照ください。 1.7.3 Access および Excel Microsoft Excel および Microsoft Access は広く一般に普及しているツールで、レポートの生成 やフォームの作成のほか、既存のデータに対する簡単なビジネス・インテリジェンスを行うためのア プリケーション開発を行うことも可能です。DB2 はこれらのツールに簡単に接続することが可能で す。データベース管理者は企業のデータをセキュアな DB2 サーバーに格納し、一般ユーザーは Access や Excel を使ってこれらのデータにアクセスしたり、レポートを生成したりすることができま す。図 1.9 に例を示します。 図 1.9 – Excel, Access と DB2 の連携例 この図では、Excel と Access はフロント・エンドのアプリケーションとして使われていることを示して おり、DB2 はデータのセキュリティー、信頼性および十分なパフォーマンスを備えたバックエンド・ システムとして描かれています。すべてのデータを DB2 に集約させたシンプルなデータの保管モ デルを示しています。 Excel の場合、DB2 にアクセスするためのもっとも簡単な方法は、IBM OLE DB Provider for DB2 などの OLE DB ドライバーを使用することです。このドライバーは、DB2 Express-C の Web サイト (http://ibm.com/db2/express ) から無償でダウンロードできる IBM Data Server Client を インストールする際に同時にインストールされます。インストール後は、目的の OLE DB Provider が使用するデータ・ソースをして初めて MS Excel のメニューから使うことができるようになります。 42 DB2 アプリケーション開発入門 Excel からは データ > 外部データの取り込み > データの取り込み を選択します。これ以降の作 業は、以下の文書をご参照ください。詳細は 参考文献 の節をご参照ください。 IBM® DB2® Universal Database™ and the Microsoft® Excel Application Developer… for Beginners [1]. Microsoft Access をご使用の場合は、以下のいずれかをインストールする必要があります。 IBM Data Server client IBM Data Server Driver for ODBC, CLI and .NET IBM Data Server Driver for ODBC and CLI IBM Data Server Driver for ODBC, CLI and .NET および IBM Data Server Driver for ODBC and CLI は共に IBM DB2 ODBC Driver としても知られており、DB2 CLI Driver とも同一のもの です。このドライバーは Access から DB2 に接続する際に使うことが可能です。ドライバーのイン ストール後、Access 2007 のプロジェクトを作成し、Table Tools リボンの External Data タブにあ る ODBC Database オプションを選択します。これ以降の作業については DB2 9 and Microsoft Access 2007 Part 1: Getting the Data...[2] に記載されています。Microsoft Access の linked tables を使えば、DB2 上にデータを配置させたまま Access 2007 ユーザーがデータを利用する ことが可能になります。 バージョン 2007 以前の Access については、セットアップ方法が多少異なりますが、Use Microsoft Access to interact with your DB2 data [3] に情報があります。詳細は参考文献の節を ご参照ください。 1.8 開発環境 DB2 のアプリケーション開発に際して、インストール作業は必須ではありません。あなたのラップト ップや企業内の PC にインストールしなくても開発が可能です。今日では、クラウド・コンピューティ ングを利用することが可能で、必要な時間だけ DB2 サーバーのサービスを活用することができま す。また、DB2 向けの仮想アプライアンスを使って DB2 のアプリケーション開発をすることも可能 です。この節では、これらの開発環境についてご説明します。 1.8.1 クラウド上で提供している DB2 のサービス DB2 はクラウド上で以下のサービスを提供しています。 Amazon Web Services IBM development and test クラウド IBM CloudBurst™ and IBM WebSphere CloudBurst アプライアンス RightscaleTM それぞれについて、以下の節でご説明します。 1.8.1.1 Amazon Web Services 第1章 DB2 アプリケーション開発の概要 43 IBM は Amazon Web Services (AWS) とのパートナーシップ契約を結び、Amazon Elastic Compute Cloud (EC2) 上で DB2 を稼動させています。AWS は、クラウド上で統合化されたサー ビスを提供し、従量課金制で利用可能になっています。すなわち、AWS は、仮想サーバーおよ びストレージを必要なだけレンタルすることが可能で使った分だけ課金されます。例えば、通常時 は EC2 上の仮想サーバー1台を使用し、ピーク時や特定期間のみ数時間の追加サーバーの利 用が必要だったとしましょう。そのようなケースでは、使用した数時間分の追加サーバー使用量の み支払えばよいことになります。 IBM は Amazon クラウド上で DB2 を利用する際の 3 つのオプションを提供しています。 評価、開発用途の DB2 Express-C Amazon Machine Images (AMIs) 重量課金制で本番運用向けの AMIs with DB2 Express and DB2 Workgroup 取得済み DB2 ライセンスを使用した個別の AMI サービス 詳細および Amazon EC2 上の DB2 の使用方法については、以下のサイトをご参照ください。 http://www.ibm.com/db2/cloud 1.8.1.2 IBM development and test cloud IBM Smart Business Development and Test on the IBM Cloud ( 略して IBM Developer Cloud) は AWS と同様のサービスを提供していますが、こちらは開発およびテスト向けに用意され ています。こちらは一定のコストで、必要に応じて資源の使用量を細かく調整することが可能です。 本書執筆時点で、IBM Developer Cloud 上の DB2 には以下の機能が含まれています。 DB2 Express-C 9.7.1 PAYG (Pay as you go). このイメージは 32-bit SUSE Linux Enterprise Server (SLES) 上の DB2 Express-C 9.7.1 が構成されています。DB2 Express-C の使用量は無料ですが、機器使用量が課金 されます。 DB2 Enterprise Developer 9.7.1 - BYOL (Bring your own license). このイメージは 32-bit SLES 上の DB2 Enterprise が構成されています。別途 IBM Database Enterprise Developer Edition (DEDE) ライセンスが必要です。 DB2 Enterprise Developer 9.7.1 64-bit - BYOL. このイメージは 64-bit Red hat Enterprise Linux (RHEL) 上に DB2 Enterprise が構成さ れています。別途 IBM Database Enterprise Developer Edition (DEDE) ライセンスが必 要です。 IBM developer Cloud に関する詳細は以下をご参照ください。 44 DB2 アプリケーション開発入門 http://ibm.com/cloud/enterprise 1.8.1.3 IBM CloudBurst for development and test IBM CloudBurst は、企業内にプライベートなクラウドを構築することができます。IBM System x® BladeCenter® プラットフォームを使用したハードウェアにミドルウェアおよびアプリケーションがプ リ・インストールされ統合化されたソリューションを提供しています。実装のための IBM サービスも 含まれています。IBM CloudBurst は、IBM WebSphere CloudBurst アプライアンスと共に使用さ れることをお勧めします。これら2つのとても重要なオファリングを組み合わせることでより簡単でク イックにサービスを提供でき、コスト的にも優位性があります。 詳細は以下をご参照ください。 http://www-01.ibm.com/software/tivoli/products/cloudburst/ 1.8.1.4 IBM WebSphere CloudBurst IBM WebSphere CloudBurst は、開発者がソフトウェアのイメージをクラウド環境にデプロイする 際に役立つアプライアンスです。WebSphere CloudBurst アプライアンスは、ソフトウェア環境をプ ライベートなクラウドに配置する「提供者」のようなものであるのに対し、IBM CouldBurst はプライ ベートなクラウド環境の「受容者」のようなものです。 本書執筆時点で、IBM Websphere CloudBurst 上には以下のような DB2 イメージが利用可能で す。 DB2 Enterprise 9.7.0 32-bit の 90 日限定試用版 このイメージは 32-bit SLES 上の DB2 Enterprise が構成されています。 詳細は以下をご参照ください。 http://www-01.ibm.com/software/webservers/cloudburst/ 1.8.1.4 Rightscale RightScale はクラウド管理のためのプラットフォームです。これにより、より簡単に、クラウド上のビ ジネス・アプリケーションをデプロイ、および管理することが可能で、自動化や各種の制御、ポータ ビリティを提供します。RightScale は RightScripts と呼ばれるサーバー向けテンプレートおよびス クリプトをサイト上で提供しており、オペレーションの多重化や繰り返しが容易にできるようになりま す。 本書執筆時点で、サーバー・テンプレートや RightScript には以下の表 1.5 ようなものが DB2 向 けに提供されています。 種類 名前 説明 サーバー・テンプレ IBM DB2 Express-C 9.7 DB2 Express-C 9.7 のインストールお 第1章 DB2 アプリケーション開発の概要 45 ート (CentOS 5.2) よび構成 サーバー・テンプレ ート IBM DB2 Express-C 9.7 (Ubuntu 8.04) DB2 Express-C 9.7 のインストールお よび構成 RightScript VPN Cubed Client Connect 既存 VPN へのサーバーの追加 RightScript Add Users to Group グループへのユーザー追加 RightScript Backup DB2 Database 使用中の DB2 インスタンスのバックア ップの実行 RightScript Create database データベースの作成 RightScript Create Group グループの作成 RightScript Create sample database db2sampl の実行 RightScript Create User ユーザーの作成 RightScript Delete Group システム・グループの削除 RightScript Delete User システム・ユーザーの削除 RightScript Drop a database データベースのドロップ RightScript Install DB2 Express-C DB2 Express-C 9.7 のインストール RightScript Remove Users from a Group グループからのユーザーの削除 RightScript Run command within db2 DB2 コマンド・ラインからのコマンド実 行 RightScript Set DB2 parameter db2set コマンドの使用 RightScript Start DB2 db2start による DB2 の起動 RightScript Start DB2 Administration Server db2admin start による DAS の起動 RightScript Stop DB2 db2stop による DB2 の停止 RightScript Stop DB2 Administration Server db2admin stop による DAS の停止 表 1.5 – DB2 用の Rightscale テンプレートおよび RightScripts 46 DB2 アプリケーション開発入門 RightScale の詳細は以下のご参照ください。 http://support.rightscale.com/27-Partners/IBM_DB2 1.8.2 VMware 向け DB2 Express-C 仮想アプライアンス 企業内で VMware を使う際は、DB2 Express-C 仮想アプライアンスが利用可能です。Linux お よび Windows の 32-bit および 64-bit が提供されています。これらのアプライアンスは以下のサイ トからダウンロード可能です。 http://www.ibm.com/db2/express/download.html 1.9 サンプル・プログラム DB2 を使って各種のプログラミング言語を学ぶ際は、DB2 サーバーをインストールしたときの SQLLIB\samples ディレクトリーにあるサンプル・アプリケーションが参考になります。以下の 図 1.10 では、Windows 版 DB2 で提供されているサンプル・プログラムのディレクトリーを紹介してい ます。 図 1.10 - DB2 に含まれるサンプル・プログラム 第1章 DB2 アプリケーション開発の概要 47 1.10 演習 1. IBM Data Studio を使って、空のストアード・プロシージャー P2 を作成してみましょう。次 にこのストアード・プロシージャーを DB2 コマンド・ウィンドウや Linux のシェルから呼び出 してみましょう。 2. IBM Data Studio を使って、パラメーターなしで固定値 2000 を返すユーザー定義関数 F2 を作成してみましょう。次にこの関数を DB2 コマンド・ウィンドウや Linux のシェルから 呼び出してみましょう。 3. P2 を修正して、そこから F2 を呼び出すようにしてみましょう。その後、動作確認をして見 ましょう。 1.11 まとめ この章では、DB2 上のデータベース・アプリケーションや DB2 に接続するクライアント・アプリケー ションに対して DB2 がどのような柔軟性を持って対応しているかをご説明しました。 サーバー・サイドのアプリケーションとしては、ストアード・プロシージャー、ユーザー定義関数、トリ ガーが含まれます。 クライアント・サイドにおいては、多種多様なプログラミング・インターフェースおよびプログラミング 手法が提供されていることをご説明しました。そして、データベース・サーバーとして DB2 が顕著 な柔軟性と機能を持っていることをご説明しました。 1.12 確認問題 1. ストアード・プロシージャーを使用することの優位性を1つ挙げましょう。 2. ユーザーが SQL 言語を拡張するにはどのような方法があるでしょうか? 3. CLI と ODBC の違いは何ですか? 4. 静的 SQL と動的 SQL の違いは何ですか? 5. JDBC Type2 と JDBC Type 4 ドライバーの違いを述べてください。 6. 以下の中で、DB2 に格納されるものはどれでしょうか? A. 表 B. ストアード・プロシージャー C. ユーザー定義関数 D. 上記すべて E. いずれも該当しない 7. 以下の中で、DB2 ストアード・プロシージャーとして使用できる言語はどれでしょうか? 48 DB2 アプリケーション開発入門 A. SQL PL B. PL/SQL C. Cobol D. Java E. 上記すべて 8. 以下の中から正しい文を選んでください。 A. 常に更新、削除、挿入が行われているデータベースにおいては、静的 SQL は通常、 動的 SQL より処理が高速である。 B. 組み込み SQL は常に静的 SQL である。 C. ODBC と JDBC は常に動的 SQL を使用している。 D. 上記すべて E. いずれも該当しない 9. 以下のうち、DB2 で推奨している ADO.NET Provider はどれでしょうか? A. ODBC .NET Data provider B. OLE DB .NET Data provider C. DB2 .NET Data provider D. 上記すべて E. いずれも該当しない 10. 以下のうち、IBM Data Server Python extension に含まれないものはどれでしょうか? A. ibm_db B. ibm_db_dbi C. ibm_db_sa D. ibm_db_python E. 上記すべて 2 第2章 – DB2 pureXML この章では、XML の native storage をサポートするために DB2 V9 で新しく導入された技術であ る pureXML についてご説明します。この章で紹介されている多くの例や概念は IBM Redbook®: DB2 9: pureXML overview and fast start からの引用です。この本の詳細については、リソースの 節を参照してください。図 2.1 は、DB2 の全体像の中で、この章が扱う部分を示しています。 図 2.1 – DB2 全体像: DB2 コマンド, SQL/XML および XQuery 50 DB2 アプリケーション開発入門 注: pureXML に関する更なる情報については、このビデオをご覧ください。 http://www.channeldb2.com/video/video/show?id=807741:Video:4382 2.1 データベースでの XML の利用 XML 文書はテキスト・ファイル、XML リポジトリー、またはデータベースとして保管できます。多くの 企業で XML 文章をデータベースに保存していますが、それには次の 2 つの理由があります。 大量の XML データの管理はデータベースで扱う問題です。XML は他のデータと同様の データであり、単にフォーマットが異なるものです。リレーショナル・データをデータベース に保存するのと同じ理由が XML データに当てはまります。すなわち、データベースによっ て、効率的な検索、データの取得、データの永続性のサポート、バックアップとリカバリー、 トランザクションのサポート、パフォーマンスとスケーラビリティーが提供されます。 統合: リレーショナル・データと XML 文書を一緒に保存することにより、新しい XML データ と既存のリレーショナル・データを統合し、SQL と XPath や XQuery を 1 つの照会にまと めることができます。さらに、リレーショナル・データを XML として公開する、あるいは、その 逆も可能です。これらの統合を通して、ベースベースが、Web アプリケーション、SOA、 Web サービスをより良くサポートできるようになります。 2.2 XML データベース XML データを保存するために 2 つのデータベースの形式があります。 XML 対応 (XML-enabled)データベース ネイティブ XML データベース 2.2.1 XML 対応(XML-enabled)データベース XML 対応のデータベースは、XML を保存するための核となるデータストレージモデルとして、リレ ーショナル・モデルを使用します。これには、(階層的な)XML データモデルとリレーショナル・デー タモデル間のマッピング、または、XML データを文字列のラージ・オブジェクトとして保存すること が必要となります。これは、以前からある技術ですが、現在でも多くのデータベース・プロバイダー によって使用されています。図 2.2 は、XML 対応データベースの 2 つのオプションについて詳し く説明しています。 第2章 – DB2 pureXML 51 図 2.2 – XML 対応(XML-enabled)データベースに XML を保存する 2 つの方式 図 2.2 の左側の図は、CLOB/Varchar を用いてデータベースに XML を保存する方式の説明で す。この方式を用いると、XML 文書はデータベースの CLOB または varchar 列に、構文解析され ていない文字列として保存されます。XML 文書が文字列として保存されている場合、XML 文書の 一部を取り出したい時に、プログラムで文字列全体を取り出してからそれを構文解析し、必要な部 分を取り出す必要があります。構文解析にあたって XML 文書の木構造をメモリー上に構築するこ とで、この木を探索することができるようになります。この方法は、メモリーを多く必要とし、かつ、高 い柔軟性はありません。 XML 対 応 デ ー タ ベ ー ス の も う 一 つ の 方 法 は 、 断 片 化 ( shredding ) ま た は 分 解 (decomposition)と呼ばれており、図 2.2 の右側で説明されています。この方式では、XML 文 章全体がテーブルに保存される小さな断片に細分化されます。この時、階層モデルである XML 文書は、リレーショナル・モデルに文字通り強制的に押し込められます。XML 文書を変更する場合、 この変更を対応するテーブルに反映することは容易ではなく、また、他に多くテーブルを作成する 必要が生じることもあるため、この方式は柔軟ではありません。また、元の XML 文書を取得する場 合、処理コストの高い SQL の join 操作を実行する必要があるため、この方式はパフォーマンスの 観点からも良いとは言えません。特に、より多くのテーブルが使われている場合、その処理コストは より高くなります。 2.2.2 ネイティブ XML データベース ネイティブ XML データベースは、階層的な XML データモデルを用いて、XML を保存し処理しま す。保存するフォーマットは、処理するフォーマットと同じです。リレーショナル・モデルへのマッピ ングは行われず、また、XML 文書は CLOB や varchars の構文解析されていない文字列としては 保存されません。XPath や XQuery ステートメントが使用される時は、そのエンジンによってそのま ま処理され、SQL に変換されることはありません。そのため、そのようなデータベースをネイティブ 52 DB2 アプリケーション開発入門 XML データベースとして知られています。DB2 は、現時点で、これをサポートする唯一の商業的 なデータベース・サーバーです。 2.3 DB2 における XML 以下の図 2.3 は DB2 ハイブリッド・データベースにリレーショナル・データと階層データ(XML 文 書)がどのようにして保存されるかの概要を表しています。また、この図は、dept 表を作成する際に 使用される CREATE TABLE ステートメントも示しています。 図 2.3 –DB2 における XML このテーブル定義では、deptdoc 列に対して新しいデータ型、XML を使用しています。図の左側 の矢印は、リレーショナル形式で保存されるリレーショナル列である deptID を指しています。一方、 XML 列である deptdoc は、構文解析された階層型の形式で保存されます。 図 2.4 は、現在、DB2 9 でデータにアクセスする方法が 4 通りあることを説明しています。: SQL を使用してリレーショナル・データにアクセスする SQL の XML 拡張 (SQL/XML)を使用して XML データにアクセスする XQuery を使用して XML データにアクセスする XQuery を使用してリレーショナル・データにアクセスする 第2章 – DB2 pureXML 53 図 2.4 – DB2 のデータにアクセスする 4 つの方法 このように、利用者の経験や知識に応じて、SQL が得意な人は DB2 を XML をサポートする世界 水準の RDBMS として見ることも可能ですし、あるいは、XML が得意な人は、 DB2 を SQL をサ ポートする世界水準の XML リポジトリーとして見ることも可能です。 IBM は、この技術を説明するためにネイティブ XML という用語の代わりに pureXML を使います。 他のベンダーは、XML 文書を保存するために、未だに CLOB/varchar や断片化といった古い技 術を用いているにもかかわらず、それらをネイティブ XML と呼んでいます。 混乱を防ぐために、 IBM は pureXML という新しい用語を使用し、他のデータベースや XML ベンダーが他の異なる技 術を同じ用語を用いて表示することのないように、商標とすることを決めました。pureXML サポート は、ユニコードまたは、非ユニコードで作成されたデータベースに対して提供されます。 2.3.1 pureXML 技術の優位点 pureXML 技術には、多くの利点があります。 1. XML 文書が新しい XML データ・タイプを使ってテーブルの列に保存されている場合には、 リレーショナル・データへの投資を意識することなく継続的に活用することができます。 2. コードの複雑さを軽減することができます。図 2.5 は、pureXML を使用した場合と、使用し ない場合の PHP スクリプトを示しています。 pureXML (左側のより小さい枠)を使用すると コードの行数が減っていることがわかります。これはコードの複雑度が減少していることの みならず、より少ないコードを構文解釈・保守すれば良くなるため、全体のパフォーマンス 向上に繋がります。 54 DB2 アプリケーション開発入門 図 2.5 – pureXML を用いた場合と用いない場合のコードの複雑度 3. XML と pureXML technology 技術でスキーマの変更がより簡単になります。図 2.6 は、こ のより高い柔軟性の例を示しています。 図の中では Employee と Department. の 2 つ の表から成るデータベースを想定しています。 XML でないデータベースでは、典型的に、 あなたのマネージャが 1 人の従業員につき 1 つの電話番号(自宅の電話)だけでなく、2 つめの電話番号(携帯電話の番号)を保存するように依頼した場合、Employee 表に列を 追加して、携帯電話の番号をその新しい列に保存することができます。しかしながら、この 方法はリレーショナル・データベースの正規化の 規則に反しています。もし規則に従う場 合には、その代わりに新しい Phone 表を作成し、全ての電話の情報をこの表に移します。 その後さらに携帯電話番号を追加します。新しい Phone 表の作成は、大量の既存のデ ータを移動する必要があるだけでなく、アプリケーションの中の全ての SQL をこの新しい 表を指すように変更しなければならないため、大きな代償がかかります。 一方、図の左側には、同じことを XML を用いてどう実現できるかを示しています。 従業 員 Christine が携帯電話の番号を持っている場合に、この情報を入れるために新しいタ グが追加できます。従業員 Michael は携帯電話の番号を持っていないので、変更は不 要です。 第2章 – DB2 pureXML 55 図 2.6 – XML を用いたデータ柔軟性の向上 4. XML アプリケーションのパフォーマンスを向上することが可能です。pureXML 技術を用い たテストは、 XML アプリケーションのパフォーマンスが大きく向上することを示しました。表 2.1 shows は、既存技術から pureXML に変更した会社のテスト結果です。2 番目の列は 他のリレーショナル・データベースを用いた旧来の方法による XML 操作の結果を示して います。3 番目の列は pureXML による DB2 を使用した結果です。 タスク 他のリレーショナル DB pureXML を持つ DB2 ビジネスプロセスの検索と取得の開 発 CLOB: 8 時間 30 分 I/O コードの相対行数 100 35 (65% reduction) スキーマへのフィールドの追加 1 週間 5分 照会 24 - 36 時間 20 秒 - 10 分 Shred: 2 時間 表 2.1 – pureXML 技術を利用したパフォーマンスの向上 2.3.2 XPath 基本 XPath は XML 文書を照会するために使われる言語です。 リスト 2.1 は XML 文書を示し、図 2.7 は同じ文書を構文解析された階層(ノードまたはリーフとも呼ばれる)形式で表わしています。 XPath がどのように機能するかを構文解析された形式を用いて説明します。 56 DB2 アプリケーション開発入門 <dept bldg=“101”> <employee id=“901”> <name>John Doe</name> <phone>408 555 1212</phone> <office>344</office> </employee> <employee id=“902”> <name>Peter Pan</name> <phone>408 555 9918</phone> <office>216</office> </employee> </dept> リスト 2.1 – XML 文書 dept employee id=901 name John Doe phone 408-555-1212 employee office id=902 344 name Peter Pan phone office 408-555-9918 図 2.7 – リスト 2.1 の XML 文書の構文解析された階層表現 XPath を素早く学ぶ方法は、 それを MS-DOS または Linux/UNIX のディレクトリー変更コマンド (cd)と比較することです。 cd コマンドを用いて、ディレクトリー木を次のように辿ることができます。 cd /directory1/directory2/… 同様に、XPath ではスラッシュを用いて XML 文書内の1つのエレメントから他のエレメントに行くこ とができます。リスト 2.1 にある文書を例にあげると、XPath では次の照会を使って全ての従業員 の名前を検索します。 /dept/employee/name 2.3.2.1 XPath 式 216 第2章 – DB2 pureXML 57 XPath 式はエレメントや属性を特定するために完全修飾されたパスを使用します。 “@” の印は、 属性を特定するために使用されます。エレメントの値 (テキスト・ノード) のみを取り出すためには、 text() 機能を使用します。表 2.2 は XPath 照会とリスト 2.1 にある XML 文書から対応する結果を 示しています。 結果 XPath /dept/@bldg 101 /dept/employee/@id 901 902 /dept/employee/name <name>Peter Pan</name> <name>John Doe</name> /dept/employee/name/text() Peter Pan John Doe 表 2.2 – XPath 式の例 2.3.2.2 XPath ワイルドカード 2 つの主なワイルドカードがあります。 “*” は任意のタグ名に合致します “//” は下位またはそれ自身のワイルドカードです 表 2.3 は、リスト 2.1 の XML 文書を用いた 幾つかの例です。 結果 XPath /dept/employee/*/text() John Doe 408 555 1212 344 Peter Pan 408 555 9918 216 /dept/*/@id 901 902 //name/text() Peter Pan John Doe /dept//phone <phone>408 555 1212</phone> <phone>408 555 9918</phone> 表 2.3 – XPath ワイルドカードの例 2.3.2.3 XPath 述部 58 DB2 アプリケーション開発入門 述部は大かっこ[ ]で囲まれます。 SQL における WHERE 句と同等に考えることができます。 例 えば [@id=”902”] は、 “WHERE id 属性 が 902 と等しい”と読めます。1つの XPath 式に複数の 述部が存在することができます。位置を示す述部を指定するためには、 n 番目の子ノードが選択 されることを意味する[n] を使用します。例えば、employee[2] は、2 番目の employee が選択され ることを示しています。表 2.4 に幾つかの例を提供します。 XPath 結果 /dept/employee[@id=“902”]/name <name>Peter Pan</name> /dept[@bldg=“101”]/employee[office >“300”]/name <name>John Doe</name> //employee[office=“344” OR office=“216”]/@id 901 902 /dept/employee[2]/@id 902 表 2.4 – XPath 述部の例 2.3.2.4 parent 軸 MS-DOS や Linux/UNIX と同様に, 現在の内容を参照していることを示すために “.” (ドット) を使 用できます。また、“..” (ドットドット) は、その親の内容を示します。表 2.5 に幾つかの例を提供しま す。 XPath 結果 /dept/employee/name[../@id=“902”] <name>Peter Pan</name> /dept/employee/office[.>“300”] <office>344</office> /dept/employee[office > “300”]/office <office>344</office> /dept/employee[name=“John Doe”]/../@bldg 101 /dept/employee/name[.=“John Doe”]/../../@bldg 101 表 2.5 – XPath parent 軸 2.3.3 XQuery 基本 XQuery は、XML のために作られた照会言語です。XQuery は、XML 階層構造を辿るためにパ ス表現をサポートします。実際、XPath は XQuery の一部です。従って、XPath に関するこれまで の記述は XQuery にも適用されます。XQuery は、型付けされたデータも型付けされていないデ ータもどちらも扱うことができます。XML 文書は存在しないまたは未知のデータを省略するので、 XQuery に null 値はありません。XQuery と XPath 表現は、大文字と小文字を区別します。また、 XQuery は、XML データのシーケンスを返します。 第2章 – DB2 pureXML 59 XQuery は FLWOR 式をサポートします。 SQL を使って説明すると、 SELECT-FROM-WHERE ステートメントに相当します。 次の節では FLWOR についてより詳しく説明します。 2.3.3.1 XQuery: FLWOR 式 FLWOR は、次の内容を表しています。 FOR: 式の結果を反復処理し、シーケンス内の各項目に変数をバインドします。 LET: 変数を式の結果全体に バインドします。 WHERE: 反復処理の項目をフィルタリングします。 ORDER: 反復処理の項目の順序を指定します。 RETURN: 照会結果を生成します。 XML 文書の操作を行う式であり、他の式を返すことが可能です。例えば、以下の定義を持つ表が あると仮定します。 CREATE TABLE dept(deptID CHAR(8),deptdoc XML); そして、リスト 2.2 にある XML 文書が deptdoc 列に挿入されています。 <dept bldg=”101”> <employee id=”901”> <name>John Doe</name> <phone>408 555 1212</phone> <office>344</office> </employee> <employee id=”902”> <name>Peter Pan</name> <phone>408 555 9918</phone> <office>216</office> </employee> </dept> リスト 2.2 - XML 文書の例 この時、 FLWOR 式を使ったリスト 2.3 にある XQuery ステートメントが実行されます。 xquery for $d in db2-fn:xmlcolumn('dept.deptdoc')/dept let $emp := $d//employee/name where $d/@bldg > 95 order by $d/@bldg return <EmpList> {$d/@bldg, $emp} 60 DB2 アプリケーション開発入門 </EmpList> リスト 2.3 - FLWOR 式を持つ XQuery ステートメントの例 これはリスト 2.4 にある結果を返します。 <EmpList bldg="101"> <name> John Doe </name> <name> Peter Pan </name> </EmpList> リスト 2.4 -リスト 2.3 の XQuery ステートメントの実行結果 2.3.4 XML 文書の挿入 DB2 データベースへの XML 文書の挿入は SQL INSERT ステートメント、または、IMPORT ユー ティリティーを使って実行されます。標準の定義が完了していないため、この目的で XQuery を使 用することはできません。 リスト 2.5 に示すスクリプト table_creation.txt を考察します。このスクリプトは、以下のステートメント を用いて DB2 コマンド・ウィンドウまたは Linux シェルから実行可能です。 db2 –tvf table_creation.txt -- (1) drop database mydb ; -- (2) create database mydb using codeset UTF-8 territory US ; -- (3) connect to mydb ; -- (4) create table items ( id int primary key not null, brandname varchar(30), itemname varchar(30), sku int, srp decimal(7,2), 第2章 – DB2 pureXML 61 comments ); xml -- (5) create table clients( id int primary key not null, name varchar(50), status varchar(10), contact xml ); -- (6) insert into clients values (77, 'John Smith', 'Gold', '<addr>111 Main St., Dallas, TX, 00112</addr>') ; -- (7) IMPORT FROM "D:\Raul\clients.del" of del xml from "D:\Raul" INSERT INTO CLIENTS (ID, NAME, STATUS, CONTACT) ; -- (8) IMPORT FROM "D:\Raul\items.del" of del xml from "D:\Raul" INSERT INTO ITEMS (ID, BRANDNAME, ITEMNAME, SKU, SRP, COMMENTS) ; リスト 2.5 - table_creation.txt ファイルの内容 こ の ス ク リ プ ト フ ァ イ ル と 関 連 す る フ ァ イ ル は 、 こ の 本 に 付 属 す る Exercise_Files_DB2_Application_Development.zip に含まれています。 リスト 2.5 のスクリプトの各行に書かれた内容に沿って説明します。 1. mydb データベースを drop します。 これは通常スクリプトファイルの中でクリ ーンアップするために行われます。それ以前に mydb が存在しない場合は、エラ ーメッセージを受け取りますが、問題ではありません。 2. UTF-8 コードセットを使って mydb データベースを作成します。これは、ユニコードのデ ータベースを作ります。 pureXML は、ユニコードと非ユニコードの両方のデータベースで サポートされます。 3. 新たに作成された mydb データベースに接続します。これはデータベースにオブジェクト を作成するために必要です。 4. items 表を作成します。 表の最後の列 ( comments 列)は、新しい XML データ型を利 用して XML 列として定義されています。 62 DB2 アプリケーション開発入門 5. clients 表を作成します。表の最後の列 (contact 列)は、新しい XML データ型として定 義されています。 6. この SQL INSERT ステートメントを使用して、XML 文書を XML 列に挿入します。 INSERT ステートメントの中にシングルクォートで囲まれた文字列として XML 文書を渡し ます。 7. IMPORT コマンドを利用して、 複数の XML 文章をリレーショナル・データと共にデータ ベースに挿入またはインポートすることができます。(7) では、clients.del ファイル (区切ら れた ascii ファイル)からデータをインポートしています。そして、clients.del ファイルによっ て参照されている XML データの場所 (この例では、D:\Raul)を示しています。 clients.del ファイルの内容についてさらに詳しく説明します。最初に、D:\Raul first ディレクトリーの 内容は図 2.8 に示す通りです。 図 2.8 - D:\Raul ディレクトリーの内容 リスト 2.6 はテキスト・ファイル clients.del の内容です。 3227,Ella Kimpton,Gold,<XDS FIL='Client3227.xml' />, 8877,Chris Bontempo,Gold,<XDS FIL='Client8877.xml'/>, 9077,Lisa Hansen,Silver,<XDS FIL='Client9077.xml' /> 9177,Rita Gomez,Standard,<XDS FIL='Client9177.xml'/>, 5681,Paula Lipenski,Standard,<XDS FIL='Client5681.xml' />, 4309,Tina Wang,Standard,<XDS FIL='Client4309.xml'/> リスト 2.6 - clients.del ファイルの内容 clients.del ファイルの中で、特定の XML ファイル文書を指定するために “XDS FIL=” が使用され ています。 第2章 – DB2 pureXML 63 図 2.9 は上記スクリプトを実行したあとのコントロール・センターを表しています。 図 2.9 – table_creation.txt スクリプト実行後のコントロール・センター 図の中で CLIENTS 表の内容が表示されています。最後の列 contact 列は XML 列です。 3 つ のドットのボタンをクリックすると別のウィンドウが開き、XML 文書の内容を表示します。これが 図 2.9.の右下になります。 2.3.5 XML データの照会 DB2 には XML データを照会する 2 つの方法があります。 SQL の XML 拡張 (SQL/XML)の使用 XQuery の使用 どちらの場合も DB2 は XML の国際標準に従っています。 2.3.5.1 SQL/XML による XML データの照会 標準の SQL ステートメントを使用して行と列を操作することができます。そして、SQL ステートメン トは、XML 文書全体を操作するために使うことも可能です。しかしながら、文書の一部だけを検索 する役には立ちません。そのような場合には、XML 拡張(SQL/XML)された SQL が必要となります。 64 DB2 アプリケーション開発入門 表 2.6 は、SQL 2006 標準で利用可能な幾つかの SQL/XML 機能を記述しています。 関数名 説明 XMLPARSE 文字とラージ・オブジェクトのバイナリー・データを構文解析 して、XML 値を生成します。 XMLSERIALIZE XML 値を文字や ラージ・オブジェクトのバイナリー・データ に変換します。 XMLVALIDATE XML 値の XML スキーマに対する妥当性検査を行い、 XML 値にタイプのアノテーションを付けます。 XMLEXISTS XQuery 式が 1 つ以上の項目のシーケンスを戻すかどうか を評価します。 XMLQUERY Xquery を実行し、結果のシーケンスを戻します。 XMLTABLE XQuery を実行し、可能であれば結果のシーケンスをリレ ーショナル表として戻します。 XMLCAST XML タイプから、または XML タイプにキャストします。 表 2.6 – SQL/XML 関数 先に作成された mydb データベースを使用して、以下の例を検証することが可能です。 例1 特定の郵便番号に住む全てのクライアントの名前を取得すること想定します。clients 表は、お客 様の郵便番号を含む住所を XML 列に保持しています。XMLEXISTS を使用して、目的の郵便番 号について XML 列を検索し、その結果セットを適切に絞り込むことが可能です。 リスト 2.7 は必 要な照会を表しています。 SELECT name FROM clients WHERE xmlexists( '$c/Client/Address[zip="95116"]' passing clients.contact as "c" ) リスト 2.7 - XMLEXISTS の使用例 リスト 2.7 にある最初の行は、 clients 表の name 列にある検索したい情報を指定する SQL 句で す。 WHERE 句で XMLEXISTS 関数を呼び出しており、そこでは、DB2 に zip エレメントを探索させ、 95116 の値をチェックする XPath 式を指定しています。 $c/Client/Address 句は、DB2 が zip エレメントの位置を特定可能にする XML 文書階層のパス を示します。ドル記号($) は、変数を指定します。従って “c” が変数となります。 この変数は、 第2章 – DB2 pureXML 65 passing clients.contact as "c" の行で定義されています。ここで、 clients は表の名前、contact は XML データ型の列の名前です。言いかえると、XML 文書を変数 “c”に渡していることになります。 DB2 は、contact 列に含まれる XML データを検査します。ルートにある Client ノードから Address ノードまで辿り、zip ノードまで到達すると、そこでその顧客が対象の郵便番号に住んで いるかどうかを判断します。XMLEXISTS 関数は真(“true” )を評価し、 DB2 はその列に関連付け られた顧客の名前を戻します。 DB2 9.5 以降では、上記照会は以下のリスト 2.8 のように単純化されています。 SELECT name FROM clients WHERE xmlexists( '$CONTACT/Client/Address[zip="95116"]' ) リスト 2.8 - リスト 2.7 に示す照会の単純化版 XML 列と同じ名前の変数が DB2 によって自動的に作られます。上記の例では、 DB2 が CONTACT という変数を自動的に作成します。その名前は XML 列 CONTACT の名前と一致し ています。 例2 ここでは、“Gold” ステータスを持つ顧客の e-mail アドレス一覧の報告書を作る問題を解決する方 法を考えます。 リスト 2.9 に示す照会がこの目的のために実行されます。 SELECT xmlquery('$c/Client/email' passing contact as "c") FROM clients WHERE status = 'Gold' リスト 2.9 - XMLQUERY の使用例 最初の行は、(リレーショナル列でない) XML 文書のエレメントである e-mail アドレスを戻したいこ とを示します。 前の例と同様に、 “$c” は XML 文書を含む変数です。 この例では、 SELECT の 後で用いられる XMLQUERY 関数を使用しています。一方で XMLEXISTS 関数は WHERE 句 の後で用いられます。 例3 XML デ ー タ を 表 と し て 表 示 し た い 状 況 が あ る か も し れ ま せ ん 。 こ れ は リ ス ト 2.10 に 示 す XMLTABLE 関数で可能になります。 SELECT t.comment#, i.itemname, t.customerID, Message FROM items i, xmltable('$c/Comments/Comment' passing i.comments as "c" columns Comment# integer path 'CommentID', CustomerID integer path 'CustomerID', Message varchar(100) path 'Message') AS t 66 DB2 アプリケーション開発入門 リスト 2.10 - XMLTABLE の使用例 最初の行は結果セットに含める列を指定しています。 “t” の変数が接頭辞に付いた列は、 XML エ レメント値を元にしています。 3 行目は、対象データ (i.comments) および対象とするエレメントの位置を特定する XML 文書列 にあるパスを含む DB2 XML 列を指定するために XMLTABLE 関数を呼び出します。 4 行目から 6 行目にある columns 句は、1 行目に指定した SQL 結果セットにある出力列にマッ プされる特定の XML エレメントを識別します。このマッピングの一部には、Part of XML エレメント 値が変換されるデータ型の指定を含みます。この例では、全ての XML データは、伝統的な SQL データ型に変換されます。 例4 ここでは、XMLQUERY SQL/XML 関数の中の XQuery FLWOR 式を含む簡単な例を見てみま す。 これはリスト 2.11.で説明します。 SELECT name, xmlquery( ‘for $e in $c/Client/email[1] return $e’ passing contact as “c” ) FROM clients WHERE status = ‘Gold’ リスト 2.11 - XMLQUERY と FLWOR の利用例 最初の行は、 顧客名と XMLQUERY 関数からの出力が結果セットに含まれることを明記します。2 行目は Client エレメントの最初の email サブエレメントが戻されることを示します。3行目は、 XML データ (contact 列) の元を識別しています。4行目はこの列が clients 表から得られること を、5行目では Gold の顧客のみを対象とすることを表します。 例5 リスト 2.12 で述べている例は、再度、 XQuery FLWOR 式を使う XMLQUERY 関数を説明してい ます。しかし、今回は XML だけでなく HTML を戻します。 SELECT xmlquery('for $e in $c/Client/email[1]/text() return <p>{$e}</p>' passing contact as "c") FROM clients WHERE status = 'Gold' リスト 2.12 - XML と HTML を戻す例 XQuery の戻り句は、 XML 出力を必要に応じて変換することを可能にします。 1 行目にある text()関数を利用して、最初の e-mail アドレスのテキスト表現だけが対象であることを示します。 2 行目は、この情報が HTML のパラグラフタグによって囲まれることを指定します。 第2章 – DB2 pureXML 67 例6 次の例は、一連のエレメント項目を作成する XMLELEMENT を使用します。それぞれの一連の項 目には、items 表の中の対応する列から得られる ID、ブランド名と在庫(SKU)に対するサブエレメ ン ト を 含 み ま す 。 基 本 的 に リ レ ー シ ョ ナ ル ・ デ ー タ を XML デ ー タ に 変 換 し た い 時 に XMLELEMENT 関数を使うことができます。 これはリスト 2.13 で説明します。 SELECT xmlelement (name "item", itemname), xmlelement (name "id", id), xmlelement (name "brand", brandname), xmlelement (name "sku", sku) FROM items WHERE srp < 100 リスト 2.13 - XMLELEMENT の使用例 リスト 2.13 の照会はリスト 2.14 に示す出力を戻します。 <item> <id>4272</id> <brand>Classy</brand> <sku>981140</sku> </item> … <item> <id>1193</id> <brand>Natural</brand <sku>557813</sku> </item> リスト 2.14 - リスト 2.13 の照会の出力 2.3.5.2 XQuery による XML データの照会 前節では、XML 拡張された SQL を用いて XML データを検索する方法を確認しました。 常に SQL が主要な検索方法で、XPath や XQuery は SQL の内部に組み込まれていました。 この節 では、XQuery を使用して XML データを検索する方法を説明します。今回は、 XQuery が主要な 検索方法で、幾つかの場合には (db2-fn:sqlquery 関数を使用して) XQuery の内部に SQL を 組み込んで使用します。 XQuery を使用する時、幾つかの新しい関数と FLWOR 式を呼び出しま す。 例1 68 DB2 アプリケーション開発入門 これは、顧客連絡先を戻す簡単な XQuery です。 この例では、 CONTACT は XML 列の名前で あり、CLIENTS は表の名前です。 xquery db2-fn:xmlcolumn(‘CLIENTS.CONTACT’) 任意の XQuery 式は、常に xquery コマンドが前に付きます。これは、XQuery パーサーを使用 する必要があることを DB2 に知らせるためであり、さもなければ、DB2 は SQL 式を実行しようとし ていることを想定します。 db2-fn:xmlcolumn 関数は、引数で指定された列から XML 文書を取 り出す関数です。この関数は、全ての列の内容を取り出しており、次の SQL ステートメントと等価で す。 SELECT contact FROM clients 例2 リスト 2.15 に示されているこの例では、顧客の client fax データを取り出すために FLWOR 式を 使用します。 xquery for $y in db2-fn:xmlcolumn(‘CLIENTS.CONTACT’)/Client/fax return $y リスト 2.15 - XQuery と FLWOR 式 最初の行では、 XQuery 構文解析器を呼び出します。2 行目で DB2 に CLIENTS.CONTACT 列に含まれる fax サブエレメントを反復処理すること指示しています。各 Each fax エレメントは、 変数 $y にバインドされます。3 行目は、各反復処理で変数“$y” の値が戻されることを示していま す。 この照会の出力は、リスト 2.16 のようになります。(複数行に展開されて読みづらくなるため、出力 の中で namespace は省略しています。) <fax>4081112222</fax> <fax>5559998888</fax> リスト 2.16 - リスト 2.15 に示す照会の出力 例3 リスト 2.17 の例は、XML データを照会し、HTML を戻します。 xquery <ul> { for $y in db2-fn:xmlcolumn(‘CLIENTS.CONTACT’)/Client/Address order by $y/zip return <li>{$y}</li> } </ul> リスト 2.17 - HTML を戻す LWOR 式を用いた XQuery ステートメント 第2章 – DB2 pureXML 69 戻される HTML の例はリスト 2.18.のようになります。 <ul> <li> <address> <street>9407 Los Gatos Blvd.</street> <city>Los Gatos</city> <state>ca</state> <zip>95302</zip> </address> </li> <address> <street>4209 El Camino Real</street> <city>Mountain View</city> <state>CA</state> <zip>95302</zip> </address> </li> ... </ul> リスト 2.18 - リスト 2.17 で実行された照会の出力 例4 次の例は、db2-fn:sqlquery 関数を使用して、SQL を XQuery に組み込む方法を示しています。 db2-fn:sqlquery 関数は SQL 照会を実行し、選択された XML データのみを戻します。db2fn:sqlquery に渡される SQL 照会は XML データだけを返す必要があります。 この XML データ は、XQuery によってさらに処理されます。リスト 2.19 でこれを説明します。 xquery for $y in db2-fn:sqlquery( ‘select comments from items where srp > 100’ )/Comments/Comment where $y/ResponseRequested=‘Yes’ return ( <action> {$y/ProductID $y/CustomerID $y/Message} </action> ) 70 DB2 アプリケーション開発入門 リスト 2.19 - XQuery 内の SQL を組み込んだ db2-fn:sqlquery 関数の例 この例の中で、SQL 照会は srp 列が 100 以上の値を持つという条件を元に行を選別します。 こ れらの選択された行から XML 列である comments 列を取り出します。次の XQuery (or XPath) は、サブエレメントに適用されます。 注: SQL は大文字、小文字を識別します。DB2 は、省略時に、全ての表と列の名前を大文字で保管 します。一方、XQuery は大文字、小文字を識別します。上記関数は、XQuery インターフェース 関数なので、全ての表名と列名は、大文字で渡されます。オブジェクト名を小文字で渡すと、オブ ジェクト名未定義のエラーになります。 2.3.6 SQL/XML による結合 この節では、異なる表にある 2 つの XML 列、または、1 つの XML 列と 1 つのリレーショナル列の 結合操作の実行方法を説明します。リスト 2.20 で示される構文で作成した 2 つの表を考えます。 CREATE TABLE dept (unitID CHAR(8), deptdoc XML) CREATE TABLE unit (unitID CHAR(8) primary key not null, name CHAR(20), manager VARCHAR(20), ... ) リスト 2.20 -結合の例で使用される表の DDL 結合操作は 2 つの方法のうちどちらかで実行します。最初の方法を 2.21 に示します。 SELECT u.unitID FROM dept d, unit u WHERE XMLEXISTS ( ‘$e//employee[name = $m]’ passing d.deptdoc as “e”, u.manager as “m”) リスト 2.21 - SQL/XML による結合の 1 つ目の方法 上のリストの 4 行目は、 dept 表の deptdoc XML 列のサブエレメントである name エレメントと unit 表の manager リレーショナル列の間で生じる結合操作です。 リスト 2.22 は、結合を実行する 2 つ目の方法を示しています。 SELECT u.unitID FROM dept d, unit u WHERE u.manager = XMLCAST( XMLQUERY(‘$e//employee/name ‘ passing d.deptdoc as “e”) AS char(20)) リスト 2.22 - SQL/XML で結合を行う 2 つ目の方法 第2章 – DB2 pureXML 71 2 つ目の方法は、リレーショナル列は JOIN の左側にあります。 リレーショナル列が等式の左側に ある場合、XML インデックスの代わりにリレーショナルインデックスが使用されるかも知れません。 2.3.7 XQuery による結合 次の表が作成されていることを仮定します。 CREATE TABLE dept(unitID CHAR(8), deptdoc XML) CREATE TABLE project(projectDoc XML) SQL/XML を使用すると、結合 はリスト 2.23 のように見えます。 SELECT XMLQUERY ( ‘$d/dept/employee’ passing d.deptdoc as “d”) FROM dept d, project p WHERE XMLEXISTS ( ‘$e/dept[@deptID=$p/project/deptID]‘ passing d.deptdoc as “e”, p.projectDoc as “p”) リスト 2.23 - SQL/XML による結合 XQuery を使用した同等の結合をリスト 2.24 に示します。 xquery for $dept in db2-fn:xmlcolumn(“DEPT.DEPTDOC”)/dept for $proj in db2-fn:xmlcolumn(“PROJECT.PROJECTDOC”)/project where $dept/@deptID = $proj/deptID return $dept/employee リスト 2.24 - XQuery による結合 2 番目の方法はより説明が簡単です。--変数 $dept は dept 表の XML 列 deptdoc にある XML 文章を保持します。 変数$proj は、project 表にある XML 列 projectdoc にある XML 文章を保 持します。 4 行目は 最初の XML 文章の属性と 2 番目の XML 文章のエレメントの間の結合操作 を実行します。 2.3.8 更新と削除操作 XML データの更新と削除は、2 つのうち 1 つの方法で実行されます。 SQL UPDATE と DELETE ステートメントの使用 TRANSFORM 式の使用 SQL UPDATE と DELETE ステートメントを使用する最初の方法では、更新または削除は文書レ ベルで発生します。すなわち、 文書全体が更新される文書で置き換えられます。例えば、 リスト 2.25 の UPDATE ステートメントにおいて、<state> エレメントだけを変更したい場合でも、実際に は XML 文書全体が置き換えられます。 UPDATE clients SET contact=( 72 DB2 アプリケーション開発入門 xmlparse(document ‘<Client> <address> <street>5401 Julio ave.</street> <city>San Jose</city> <state>CA</state> <zip>95116</zip> </address> <phone> <work>4084633000</work> <home>4081111111</home> <cell>4082222222</cell> </phone> <fax>4087776666</fax> <email>[email protected]</email> </Client>') ) WHERE id = 3227 リスト 2.25 - SQL UPDATE の例 2 番目の方法では、TRANSFORM 式を使用して文章の一部の更新が可能であり、それはより効 果的です。これは XML 文章にあるノードの置換、挿入、削除または名前の変更を可能にします。 ノード自体を置き換えることなく、ノードの値の変更が可能です。典型的には、エレメントや属性の 値の変更が非常に一般的な更新の形です。このサポートは、DB2 9.5 に追加されました。 TRANSFORM 式は、XQuery 言語の一部です。例えば、 FLWOR 式や SQL/XML ステートメン トの XMLQUERY 関数の中など、 XQuery を通常使用するどの場所でも使用することが可能です。 最も典型的な利用は、XML 列にある XML 文章を更新する SQL UPDATE ステートメントの中で す。 リスト 2.26 は、TRANSFORM 式の構文を示しています。 >>-transform--| copy clause |--| modify clause |--| return clause |->< copy clause .-,---------------------------------------. V | |--copy----$VariableName--:=--CopySourceExpression-+------------| modify clause |--modify--ModifyExpression-------------------------------------| return clause 第2章 – DB2 pureXML 73 |--return--ReturnExpression-------------------------------------| リスト 2.26 - TRANSFORM 式の構文 copy 句は、処理したい XML 文章を変数に割り当てるために使われます。 modify 句では、insert, delete, rename, または replace 式を起動することができます。これらの式 は、XML 文章への変更を実施することを可能にします。 例えば、 • 文章に新しいノードを作成する場合、insert 式を使用します。 • XML 文章からノードを削除するためには、delete 式を使用します。 • XML 文章の中のエレメントや属性の名前を変更するためには、 rename 式を使用します。 • 既存のノードを新しいノード、または、一連のノードで置き換えるためには、replace 式を 使用します。式の置換値はエレメントや属性の値を変更するためだけに使用されます。 return 句は、transform 式の結果を戻します。 リスト 2.27 は、TRANSFORM 式を利用した UPDATE ステートメントの例を示します。 (1)-- UPDATE customers (2)-- SET contactinfo = xmlquery( 'declare default element namespace (3)-"http://posample.org"; (4)-- transform (5)-- copy $newinfo := $c (6)-modify do insert <email2>my2email.gm.com</email2> (7)-as last into $newinfo/customerinfo (8)-- return $newinfo' passing contactinfo as "c") (9)-- WHERE id = 100 リスト 2.27 - TRANSFORM 式を使用した UPDATE 上の例において、 (1), (2)と (9) の行は SQL UPDATE 構文の一部です。行 (2) で XMLQUERY 関数が起動され、それが行 (4)の transform 式を呼び出します。transform 式は、 行 (4) から行 (8)にかけて書かれており、email2 エレメントを含む XML 文書の中に新しいノードを挿入するため に使われます。ビューを通した XML 文書内のエレメントの更新はサポートされません。 表から XML 文書全体を削除することは、SQL/XML.の中で SELECT ステートメントを使用する時 と同じ位簡単なことです。SQL DELETE ステートメントを使用し、任意の必要な WHERE 述部を 指定します。 2.3.9 XML インデックス XML 文書において、エレメント、属性または値(テキスト・ノード)に対してインデックスを作成するこ とができます。幾つかの例を下に挙げます。次の表が作成されたものと仮定します。 CREATE TABLE customer(info XML) 74 DB2 アプリケーション開発入門 そして、リスト 2.28 の文書が、表に保存されている文書の1つであるとします。 <customerinfo Cid="1004"> <name>Matt Foreman</name> <addr country="Canada"> <street>1596 Baseline</street> <city>Toronto</city> <state>Ontario</state> <pcode>M3Z-5H9</pcode> </addr> <phone type="work">905-555-4789</phone> <phone type="home">416-555-3376</phone> <assistant> <name>Peter Smith</name> <phone type="home">416-555-3426</phone> </assistant> </customerinfo> リスト 2.28 - XML インデックスに関する例の中で使用する XML 文章 リスト 2.29 に示すステートメントが 属性 Cid 上にインデックスを作成します。 CREATE UNIQUE INDEX idx1 ON customer(info) GENERATE KEY USING xmlpattern '/customerinfo/@Cid' AS sql DOUBLE リスト 2.29 - Cid 属性のインデックス リスト 2.30 のステートメントはエレメント name 上にインデックスを作成します。 CREATE INDEX idx2 ON customer(info) GENERATE KEY USING xmlpattern '/customerinfo/name' AS sql VARCHAR(40) リスト 2.30 - name エレメントのインデックス リスト 2.31 のステートメントは 全てのエレメント name 上にインデックスを作成します。 CREATE INDEX idx3 ON customer(info) GENERATE KEY USING xmlpattern '//name' AS sql VARCHAR(40); リスト 2.31 - 全ての name エレメントに対するインデックス リスト 2.32 のステートメントは全てのテキスト・ノード (全ての値)上にインデックスを作成します。 こ れは、更新、削除と挿入の操作に対してインデックスを維持するコストが高く、またインデックスが大 きくなり過ぎるため、推奨されません。 CREATE INDEX idx4 ON customer(info) 第2章 – DB2 pureXML 75 GENERATE KEY USING xmlpattern '//text()' AS sql VARCHAR(40); リスト 2.32 - 全てのテキスト・ノードに対するインデックス (非推奨) 2.4 XML スキーマを用いた作業 DB2 は、それが整形式である場合に、 XML 文書をデータベースに挿入することを可能にします。 整形式でない場合は、挿入時にエラーが発生します。一方で、DB2 は、XML 文書の妥当性検査 を強要しません。妥当性検査を行いたい場合は、この節の中で議論する幾つかの代替案がありま す。 2.4.1 XML スキーマの登録 XML スキーマは、DB2 データベースの XML スキーマレポジトリに保存されます。XML スキーマ をレポジトリに追加するために、 REGISTER XMLSCHEMA コマンドを使用します。 例えば、図 2.10 に示す order.xml ファイルに保存された XML 文書があるとします。 Figure 2.10 - The order.xml file containing an XML document 次に、図 2.11 に示す order.xsd ファイルに保存された XML スキーマ文書を考えます。 76 DB2 アプリケーション開発入門 図 2.11 - XML スキーマを含む order.xsd ファイル この XML スキーマ文書の中で 次の個所を楕円で強調しています。 <xsd:schema ….>: XML スキーマ文書であることを示します。 <xsd:import …>: このより大きな XML スキーマの一部である他のファイル (他の other XML スキーマ) をインポートします。 minOccurs=“1”: XML スキーマ規則の例です。最低でも一度は Item エレメントが生じる、 言い換えれば、最低一つの Item エレメントが存在します。 次に、XML スキーマをデータベースに登録するために、以下のリスト 2.33 に示すのと同様のスク リプトが使用されます。このスクリプトは、自身を説明するコマントを含みます。 -- CONNECT TO THE DATABASE CONNECT TO SAMPLE; -- REGISTER THE MAIN XML SCHEMA REGISTER XMLSCHEMA http://www.test.com/order FROM D:\example3\order.xsd AS order; -- ADD XML SCHEMA DOCUMENT TO MAIN SCHEMA 第2章 – DB2 pureXML 77 ADD XMLSCHEMA DOCUMENT D:\example3\header.xsd; TO order ADD http://www.test.com/header FROM -- ADD XML SCHEMA DOCUMENT TO MAIN SCHEMA ADD XMLSCHEMA DOCUMENT TO order ADD D:\example3\product.xsd; http://www.test.com/product FROM -- ADD XML SCHEMA DOCUMENT TO MAIN SCHEMA ADD XMLSCHEMA DOCUMENT TO order ADD D:\example3\customer.xsd; http://www.test.com/customer FROM -- COMPLETE THE SCHEMA REGISTRATION COMPLETE XMLSCHEMA order; Listing 2.33 - A sample script showing the steps to register an XML schema この情報をあとで観閲するために、リスト 2.34 に示されるカタログ表から情報を SELECT すること ができます。 SELECT CAST(OBJECTSCHEMA AS VARCHAR(15)), CAST(OBJECTNAME AS VARCHAR(15)) FROM syscat.xsrobjects WHERE OBJECTNAME='ORDER‘; リスト 2.34 - DB2 カタログ表からの XML スキーマ情報の取得 2.4.2 XML スキーマの妥当性検査 一度 XML スキーマが DB2 に登録されると、XML 文書を 2 つの方法で妥当性を検査することが できます。 INSERT の間で XMLVALIDATE 関数を使用する BEFORE トリガーを使用する 図 2.12 は、図 2.10 の XML 文書が図 2.11 に示される XML スキーマに従って妥当性検査が行 われる例です。 78 DB2 アプリケーション開発入門 図 2.12 - XMLVALIDATE を使用した XML スキーマの妥当性検査 XML 文 書 の 妥 当 性 が 検 査 さ れ た か ど う か を 確 認 す る た め に 、 CHECK 制 約 の 上 で “IS VALIDATED” 述部を利用することができます。 列にある XML 文書を異なる XML スキーマを使用して、妥当性検査を行うことができます。これは、 XML スキーマの第一版から第二版に簡単に移行するために重要です。同じ XML 列の中で、全く 妥当性検査されていない XML 文書があるかも知れません。これは、信頼された提供元とスキーマ の妥当性検査が必要な信頼されていない提供元の両方から文書を受け取る場合に役に立ちます。 2.4.3 他の XML サポート 小さな XML 文書は、基本の表にインラインで格納されます。これは XML データがリレーショナ ル・データと同じ場所に保存され、普通のリレーショナル・データと同じ圧縮の仕組みを利用できる 利点があることを意味します。大きな XML 文書は、それもまた圧縮可能ですが、異なる内部のオ ブジェクトの中に保存されます。 第2章 – DB2 pureXML 79 DB2 は XML スキーマ展開もサポートします。これは、XML スキーマが変化する場合、UPDATE XMLSCHEMA コマンドを用いて XML スキーマを簡単に更新できることを意味します。 XML スキ ーマの変更があまりにも大幅な場合には、 幾つかのエラーが発生しがちになります。 DB2 では、 XML 分解(decomposition )または断片化(“shredding”)もサポートします。これは XML をデータベースに保存する旧来の方法で、他のベンダーが XML を保存するために使用し ています。DB2 はユーザーが希望すれば現在でもこの方法をサポートしますが、pureXML を推 奨します。DB2 は XML Extender もサポートします。これも、XML を保存するために旧来の方法 を使用しており、この Extender はこれ以上拡張されることはありません。 DB2 9.7 で、全ての pureXML の利点がデータウェアハウスのために一般的に利用されるデータ ベース・パーティションにも拡張されました。データベース・パーティション・フィーチャー (DPF) は、 DB2 Enterprise Edition で提供されます。 2.5 演習 この章を通して、SQL/XML と XQuery 構文の幾つかの例を見てきました。また、DB2 コマンド・エ ディターと IBM Data Studio を紹介しました。 この演習では、これらのツールの経験を得ると同時 に SQL/XML と XQuery の知識を確認します。この章の以前に説明した table_creation.txt スク リプトファイル(リスト 2.5)を用いて作成した mydb データベースを使用します。 (手順) 1. この章の初めに説明したように、mydb データベースを作成し XML データをロー ド し ま す 。 table_creation.txt フ ァ イ ル は 、 2 章 フ ォ ル ダ ー の 下 に あ る 付 属 の Exercise_Files_DB2_Application_Development.zip ファイルに含まれています。 DB2 コ マ ン ド ・ ウ ィ ン ド ウ ま た は Linux シ ェ ル か ら 以 下 の よ う に table_creation.txt スクリプトファイルを実行します。 db2 –tvf table_creation.txt 2. スクリプトがいずれかの手順で失敗した場合は、エラーメッセージを確認して、問題を解決 することを試みてください。 スクリプトを実行している時の典型的な問題は、ファイルが異 なるディレクトリーにあるかも知れないので、そのパスを変更する必要があることかも知れま せん。DB2 コマンド・ウィンドウまたは Linux シェルから次のコマンドを実行して、いつでも データベースをドロップし、再度開始することができます。 db2 drop database mydb 3. データベースのドロップを試みている間に活動中の接続があるという原因でエラーが発生 した場合、最初にこのコマンドを実行します。 db2 force applications all 4. スクリプトの実行が成功した後で、DB2 コントロール・センターまたは IBM Data Studio を 利用して、items と clients 表が作成され、それぞれ 4 つの行と 7 つの行を含んでいるこ とを確認します。 80 DB2 アプリケーション開発入門 5. 作成された mydb データベースとロードされた 2 つの表を用いて、それらに接続し、リスト 2.7 から 2.19 に示された照会を実行することができます。 2.6 まとめ この章では XML と pureXML 技術を紹介しました。XML は、 Web 2.0 ツールと技術、そして SOA によって、その利用が急激に増大します。XML 文書を DB2 データベースに保存することに よって、pureXML を利用してセキュリティー、パフォーマンス、コーディングの柔軟性という利点を 利用することができます。pureXML は、構文解析された階層化形式、つまり木形式で XML 文書 を保存することを可能にする技術です。そして、これはデータベースへの挿入時に行われます。照 会時には、処理の前に木構造を作るために XML 文書を構文解析する必要はありません。XML 文 書に対する木 は既に構築されデータベースに保存されています。加えて、pureXML 技術は XQuery を理解するネイティブ XML エンジンを使用します。従って、他の RDBMS 製品で行われ ているように XQuery を SQL に置き換える必要はありません。 この章は SQL/XML と XQuery を使用して XML 文書を挿入、削除、更新そして照会する方法に ついても話しました。XML インデックス、XML スキーマ、そして圧縮や XML スキーマ展開などの 他の機能についても議論しました。 2.7 確認問題 1. ファイルではなく、データベースの中に XML 文書を保存することが良いのは何故ですか? 2. XML データ保存するための 2 つのデータベースの形式は何ですか? 3. pureXML の 2 つの主な特徴は何ですか? 4. pureXML がアプリケーションパフォーマンスにとって良いのは何故ですか? 5. XML 文書を DB2 データベースにどのように挿入することができますか? 6. DB2 にある XML データを取り出すために次のどれが利用できますか? A. SQL B. SQL/XML C. XQuery D. B and C E. 上記全て 7. 次のうち SQL/XML 関数でないのはどれですか? A. XMLQUERY B. XMLTABLE C. XMLCAST D. XMLVALIDATE 第2章 – DB2 pureXML 81 E. XMLNAVIGATE 8. 次のうち XQuery 関数でないのはどれですか? A. db2-fn:xmlcolumn B. db2-fn:sqlquery C. XMLQUERY D. 上記全て E. 上記いずれでもない 9. どのように XML 文書を更新することができますか? A. SQL INSERT ステートメントを使用する B. TREEUPDATE 式を使用する C. TRANSFORM 式を使用する D. 上記全て E. 上記いずれでもない 10. 次のうち正しいステートメントはどれですか? A. XML インデックスは、エレメント、属性に対して作成され、値については作成されない B. XML スキーマはデータベースとは関連のない別の内部ファイルである XML スキー マレポジトリに保存される C. AFTER トリガーで XML 文書の妥当性検査ができる D. 上記全て E. 上記いずれでもない 3 第 3 章 – ストアード・プロシージャー、ユーザー定義 関数、トリガー、Data Web サービス. 本章では、ストアード・プロシージャー、ユーザー定義関数 (UDF) およびトリガーを使用した、 デ ータ・サーバー・サイドでの開発に着目します。 ストアード・プロシージャーは、SQL ステートメントとビジネス・ロジックをカプセル化することのできる、 データベース・アプリケーション・オブジェクトです。アプリケーション・ロジックをデータベースの中に 保管しておくことにより、アプリケーションとデータベースの間のネットワーク・トラフィックを削減する ことができるため、パフォーマンスの向上につながります。さらに、ストアード・プロシージャーを使用 することにより、ソース・コードを一箇所に集中して保管できるため、他のアプリケーションも同じスト アード・プロシージャーを再利用することが可能です。 UDF を使用すると、SQL 言語を拡張することができ、ビジネス・ロジックをカプセル化することがで きます。 トリガーは、データベース管理者が、データ挿入前のデータの妥当性をデータ・サーバーに自動 的に確認させたり、データの変更後にデータを監査したりすることができるデータベース・オブジェ クトです。 Data Web サービスは、SQL スクリプトやストアード・プロシージャーを Web サービスに変換するこ とにより、DB2 データベースの情報を外部化します。これにより、データベースに格納されている情 報を共有する必要のある企業に対し、柔軟性があり、低コストで利便性の高いソリューションを提供 します。 本章では、以下の点をご説明します。 SQL PL と Java ストアード・プロシージャーの基礎 ユーザー定義関数の開発 Data Web サービスの作成 IBM Data Studio の利用 BEFORE, AFTER, INSTEAD OF トリガーの作成 84 DB2 アプリケーション開発入門 3.1 ストアード・プロシージャー: 概要 DB2 ストアード・プロシージャーは、SQL PL (SQL プロシージャー型言語) 、C/C++、Java、 COBOL、CLR (共通言語ランタイム) サポートの言語、OLE で記述することが可能です。この章で は、一般的によく使用されており、パフォーマンスがよく、単純であることから、SQL PL プロシージ ャーに着目します。また、Java 言語を使用したストアード・プロシージャーの作成方法についても 簡単に述べます。 注: Oracle の SQL/PSM の拡張であり、ストアード・プロシージャーと共に使用される PL/SQL (Procedural Language / SQL) は V9.7 で新たにサポートされるようになりました。DB2 ExpressC エディションは、現在 PL/SQL をサポートしていません。 図 3.1 でストアード・プロシージャーの挙動を示しています。 図 3.1 – ストアード・プロシージャーによるネットワーク・トラフィックの削減 図の上部左端に、順番に実行されている SQL ステートメントが表示されています。各 SQL はクラ イアントからデータ・サーバーに送信され、データ・サーバーはクライアントに結果を返します。もし 多くの SQL ステートメントがこのように実行されると、ネットワーク・トラフィックは増加します。一方、 図の下部では、より少ないネットワーク・トラフィックで実行できる別の方法が表示されています。こ の二つ目の方法では、サーバーに保管された、 myproc というストアード・プロシージャーを call し ており、このストアード・プロシージャーは一つ目の方法と同じ SQL を含んでいます。そしてクライ アント側 (図の左側) では、ストアード・プロシージャーを呼び出すために CALL ステートメントが使 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 85 用されています。この二つ目の方法では、ネットワークを経由するのは一つの call ステートメントの みであり、クライアントに戻される結果セットも一つであるため、より効率的です。 ストアード・プロシージャーは、データベースのセキュリティーを維持する意味でも有効です。例え ば、ユーザーからの表やビューへのアクセスをストアード・プロシージャー経由のみに制限すること ができ、サーバーを厳重に管理し、ユーザーがアクセスすることを想定していない情報へのアクセ スを防ぐことができます。これが可能なのは、ストアード・プロシージャーを経由してアクセスする場 合には、ユーザーは表やビューに対する明示的な特権を必要とせず、ストアード・プロシージャー を起動するのに必要な特権のみを持っていれば良いからです。 注: SQL PL ストアード・プロシージャーについて、より詳細な情報が必要な場合には、以下のビデオを 参照してください。 http://www.channeldb2.com/video/video/show?id=807741:Video:4343 3.2 IBM Data Studio の利用 IBM Data Studio 2.2 は、本章でストアード・プロシージャー、UDF 、Data Web サービスを開発 するのに使用します。IBM Data Studio 2.2 は無償です。DB2 には同梱されておらず、別個のイメ ージとして提供されます。以下の二通りの提供方式があります。 IDE: InfoSphere Data Architect やラショナル製品など、他の製品と同一の Eclipse を共 用することができます (シェルの共用) 。また、Data Web サービスのサポートも提供します。 スタンドアロン: このバージョンは、IDE バージョンとほぼ同等の機能を提供しますが、Data Web サービスのサポートとシェルの共用の機能はありません。このバージョンの方がサイ ズは小さいです。 注: IBM Data Studio 全体のより詳細な情報については、無償の eBook である Getting started with IBM Data Studio for DB2 を参照してください。これは DB2 on Campus の無償の eBook シリーズの一部です。 本章では、Data Web サービスとの使用方法について実演するため、IDE バージョンを使用しま す。Data Studio のイメージは、 http://www.ibm.com/db2/express/download.html からダウンロ ードできます。図 3.2 は、IBM Data Studio 2.2 を示しています。 86 DB2 アプリケーション開発入門 図 3.2 – IBM Data Studio 2.2 本章では、図の左上で印がつけられているデータ・プロジェクト・エクスプローラー ビューに着目し ます。このビューはサーバー・サイドでの開発で使用されます。 3.2.1 プロジェクトの作成 ストアード・プロシージャー、UDF 、Data Web サービスを Data Studio で開発する前に、プロジェ クトを作成する必要があります。Data Studio のメニューから、ファイル -> 新規 -> プロジェクト をク リックし、データ開発プロジェクト を選択してください。図 3.3 に画面が示してあります。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 87 図 3.3 – データ開発プロジェクトの作成 ウィザードからステップに従い、プロジェクトの名前を入力し、そのプロジェクトをどのデータベース に関連付けたいかを指定してください。既存のデータベース接続がない場合には、接続の選択 パ ネルで 新規 ボタンをクリックすると、図 3.4 で示されているウィンドウが開きます。 88 DB2 アプリケーション開発入門 図 3.4 – 新規接続のパラメーター 図 3.4 では、左側にあるデータベース・マネージャーの選択 フィールドで DB2 for Linux, UNIX および Windows を選択するようにしてください。DB2 for Linux, UNIX および Windows を選択し た場合、JDBC ドライバー ドロップ・ダウン・メニューのデフォルトは IBM Data Server Driver for JDBC and SQLJ (JDBC 4.0) デフォルト としてリストされる JDBC タイプ 4 ドライバーです。この デフォルトのドライバーを使用し、残りのフィールドも入力してください。ホストフィールドには、IP ア ドレスまたはホスト名を入力することができます。この例では、IBM Data Studio と DB2 は同じコン ピューター上に存在しているので、localhost が選択されています。データベースへの接続に問 題がないかをテストするために、図の左下の端に表示されている 接続のテスト ボタンをクリックして ください。接続テストに成功した場合は、終了 ボタンをクリックしてください。これにより、プロジェクト を関連付けることのできる接続のリストにデータベースの名前が追加されます。データベースを選 択し、終了 ボタンをクリックすると、データ・プロジェクト・エクスプローラー ビューにプロジェクトが表 示されます。このビューで "+" 記号をクリックすると、プロジェクトをドリルダウンし、PL/SQL パッケ ージや SQL スクリプト、ストアード・プロシージャーなどの別のフォルダーを見ることができます。 3.2.2 ストアード・プロシージャーの作成. Java、PL/SQL または SQL PL のストアード・プロシージャーを Data Studio で作成するには、以 下の手順に従ってください。その他の言語のストアード・プロシージャーは Data Studio では作成 できないことにご注意ください。以下の手順では、ストアード・プロシージャーの言語として SQL (SQL PL を示します。) を選択していますが、Java および PL/SQL 言語でも同じような手順を使 用することができます。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 89 ステップ 1: ストアード・プロシージャーのコードの記述または作成 ストアード・プロシージャーを作成したい場合には、ストアード・プロシージャー フォルダー上で右ク リックし、新規 -> ストアード・プロシージャー を選択してください。プロシージャーを関連付けるプロ ジェクトやプロシージャーの名前、言語、プロシージャーで使用する SQL ステートメントなど、 新 規ストアード・プロシージャー ウィザードで要求された情報を入力してください。デフォルトでは、 Data Studio は SQL ステートメントの例を表示します。その他のパネルでは全てデフォルトを使用 するか、この時点で 終了 をクリックすると、テンプレートのコードや例として表示された SQL ステー トメントを使用してストアード・プロシージャーが作成されます。これは図 3.5 で表示されています。 図 3.5 – サンプル・ストアード・プロシージャー 図 3.5 では、MYPROCEDURE というサンプル・ストアード・プロシージャーのコードが生成されて います。このコードを独自のコードに全て置き換えることも可能です。わかりやすくするために、この 本では上記のサンプル・ストアード・プロシージャーを自分たちが書いたもののようにして使っていく ことにします。 ステップ 2: ストアード・プロシージャーのデプロイ ストアード・プロシージャーの作成後、デプロイするには、データ・プロジェクト・エクスプローラー ビ ューからそのプロシージャーを選択し、右クリックして デプロイ を選択してください。ストアード・プロ シージャーのデプロイは、基本的には CREATE PROCEDURE ステートメントを実行し、プロシー ジャーをコンパイルし、データベースに保管することです。図 3.6 がこのステップを示しています。 90 DB2 アプリケーション開発入門 図 3.6 – ストアード・プロシージャーのデプロイ デプロイ をクリックした後、通常は デプロイ・オプション パネルでデフォルトを使用し、終了 をクリッ クすれば十分です。 ステップ 4: ストアード・プロシージャーの実行 ストアード・プロシージャーをデプロイしたら、そのプロシージャーの上で右クリックし、実行 を選択 することによって実行することができます。結果は図 3.7 で表示されている Data Studio ワークベ ンチ ウィンドウの 右下の端にある結果 タブに表示されます。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 91 図 3.7 – ストアード・プロシージャー実行後の出力 ストアード・プロシージャーを DB2 コマンド・ウィンドウまたはコマンド・エディターから実行するには、 CALL <プロシージャー名> ステートメントを使用することができます。ストアード・プロシージャーは データベースに存在しているため、最初にデータベースに接続する必要があることを忘れないでく ださい。図 3.8 がこれを示しています。 92 DB2 アプリケーション開発入門 図 3.8 – DB2 コマンド・ウィンドウからのストアード・プロシージャーの呼び出し DB2 コマンド・ウィンドウからストアード・プロシージャーが呼び出せるのと同じように、Java プログラ ム、C プログラム、Visual Basic プログラムなどからも呼び出すことができます。各言語の正しいシ ンタックスを使うだけで呼び出しが可能です。 3.3 SQL PL ストアード・プロシージャーの基礎 SQL PL ストアード・プロシージャーは、簡単に作成し、試すことができます。このプロシージャーは DB2 で最も良いパフォーマンスを発揮します。本章では、SQL PL ストアード・プロシージャー (単 に “SQL プロシージャー” とも呼ばれます。) に焦点を当てます。 3.3.1 ストアード・プロシージャーの構造 ストアード・プロシージャーの基本的な構文は以下の通りです。 CREATE PROCEDURE プロシージャー名 [( {任意のパラメーター} )] [任意のプロシージャー属性] <ステートメント> <ステートメント> には、単一のステートメント、または BEGIN [ATOMIC] ... END でグループ化された ステートメントのセットが入ります。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 93 3.3.2 任意のストアード・プロシージャー属性 任意のストアード・プロシージャー属性を以下に示します: LANGUAGE SQL この属性は、ストアード・プロシージャーが使用する言語を示します。LANGUAGE SQL がデ フォルト値です。Java や C 言語などのその他の言語には、それぞれ LANGUAGE JAVA ま たは LANGUAGE C を使用してください。 RESULT SETS <n> この属性は、ストアード・プロシージャーが n 個の結果セットを戻す場合に必要です。 SPECIFIC my_unique_name これは、プロシージャーに与えられる固有の名前を示します。ストアード・プロシージャーはオ ーバーロードすることができます。つまり、パラメーターの数が異なるいくつかのストアード・プロ シージャーが、同じ名前を持つことができます。SPECIFIC キーワードを使用することにより、 これらのストアード・プロシージャーのそれぞれに固有の名前をつけることができ、ストアード・ プロシージャーの管理が容易になります。例えば、SPECIFIC キーワードを使用してストアー ド・プロシージャーをドロップするには、以下のステートメントを使用します: DROP SPECIFIC PROCEDURE 。もし SPECIFIC キーワードを使用しなかった場合には、ドロップするプロシ ージャーがオーバーロードされたプロシージャーのうちのどれなのかを DB2 が特定できるよう にするために、DROP PROCEDURE ステートメントを使用し、プロシージャーの名前と全て のパラメーターを指定する必要があります。 3.3.3 パラメーター SQL PL ストアード・プロシージャーには、3 つのタイプのパラメーターがあります: IN – 入力パラメーター OUT – 出力パラメーター INOUT – 入力および出力パラメーター 例: CREATE PROCEDURE proc(IN p1 INT, OUT p2 INT, INOUT p3 INT) プロシージャーを呼び出すためには、 CALL ステートメントを使用します。例えば、上記のストアー ド・プロシージャーを呼び出すには、以下のように指定します: CALL proc (10,?,4) 疑問符 (?) は CALL ステートメントの OUT パラメーターに使用されます。リスト 3.1 は、その他の パラメーターを使用したストアード・プロシージャーの例を示しています。 CREATE PROCEDURE P2 ( IN INOUT v_p2 INT, OUT v_p3 INT) LANGUAGE SQL SPECIFIC myP2 v_p1 INT, 94 DB2 アプリケーション開発入門 BEGIN -- my second SQL procedure SET v_p2 = v_p2 + v_p1; SET v_p3 = v_p1; END リスト 3. 1 – パラメーターを使用したストアード・プロシージャー コマンド・エディターからプロシージャーを呼び出す場合には、以下のようなステートメントを使用し ます: call P2 (3, 4, ?) 3.3.4 SQL PL ストアード・プロシージャーのコメント SQL PL ストアード・プロシージャーでコメントを指定する方法は二つあります。 ダッシュを二つ使用する。例: -- This is an SQL-style comment C 言語と似たフォーマットを使用する。例: /* This is a C-style coment */ 3.3.5 コンパウンド・ステートメント ストアード・プロシージャーの中のコンパウンド・ステートメントは、BEGIN と END のキーワードでカ プセル化された、いくつかのプロシージャー命令と SQL ステートメントで構成されたステートメント です。BEGIN キーワードの後に ATOMIC キーワードが続いている場合は、コンパウンド・ステート メントは一つの単位として扱われます。つまり、そのコンパウンド・ステートメントが正常終了するため には、そのコンパウンド・ステートメントに含まれる全ての命令やステートメントが正常終了する必要 があります。もしステートメントの一つが正常終了しなかった場合には、全てがロールバックされま す。図 3.9 は、コンパウンド・ステートメントの構造を示しています。 図 3.9 – コンパウンド・ステートメント 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 95 3.3.6 変数の宣言 変数を宣言するには、以下のように DECLARE ステートメントを使用します。 DECLARE var_name <data type> [DEFAULT value]; リスト 3.2 でいくつかの例を示しています。 DECLARE temp1 SMALLINT DEFAULT 0; DECLARE temp2 INTEGER DEFAULT 10; DECLARE temp3 DECIMAL(10,2) DEFAULT 100.10; DECLARE temp4 REAL DEFAULT 10.1; DECLARE temp5 DOUBLE DEFAULT 10000.1001; DECLARE temp6 BIGINT DEFAULT 10000; DECLARE temp7 CHAR(10) DEFAULT 'yes'; DECLARE temp8 VARCHAR(10) DEFAULT 'hello'; DECLARE temp9 DATE DEFAULT '1998-12-25'; DECLARE temp10 TIME DEFAULT '1:50 PM'; DECLARE temp11 TIMESTAMP DEFAULT '2001-01-05-12.00.00'; DECLARE temp12 CLOB(2G); DECLARE temp13 BLOB(2G); リスト 3.2 – 変数の宣言の例 3.3.7 代入文 変数に値を割り当てるには、SET ステートメントを使用します。例: SET total = 100; 上記のステートメントは、以下と同等です VALUES(100) INTO total; 加えて、どの変数も NULL に設定することができます。例: SET total = NULL; SELECT ステートメントの出力を基に変数に値を割り当てることもできます。例: SET total = (select sum(c1) from T1); SET first_val = (select c1 from T1 fetch first 1 row only) 96 DB2 アプリケーション開発入門 表から二つ以上の値がフェッチされ、それを一つの変数に割り当てようとした場合には、エラーに なります。二つ以上の値を保存する必要がある場合、配列かカーソルを利用してください。 データベースのプロパティーや DB2 の特殊レジスターに基づいて変数を設定することも可能です。 例: SET sch = CURRENT SCHEMA; 3.3.8 カーソル カーソルは、SELECT ステートメントの結果を保持する結果セットです。カーソルの宣言、オープン、 フェッチ、クローズのための構文はリスト 3.3 で示しています。 DECLARE <cursor name> CURSOR [WITH RETURN <return target>] <SELECT statement>; OPEN <cursor name>; FETCH <cursor name> INTO <variables>; CLOSE <cursor name>; リスト 3.3 – カーソル操作のための構文 カーソルが宣言された場合、WITH RETURN 節を以下の値と共に使用することができます: CLIENT: 結果セットはクライアント・アプリケーションに戻されます。 CALLER: 結果セットはクライアントまたは呼び出し元のストアード・プロシージャーに戻さ れます。 以下のリスト 3.4 で、カーソルを使用したストアード・プロシージャーの例を示します。 CREATE PROCEDURE set() DYNAMIC RESULT SETS 1 LANGUAGE SQL BEGIN DECLARE cur CURSOR WITH RETURN TO CLIENT FOR SELECT name, dept, job FROM staff WHERE salary > 20000; OPEN cur; END リスト 3.4 – カーソルを使用したストアード・プロシージャー 3.3.9 フロー制御 他の多くの言語と同様に、SQL PL にはロジックのフローを制御するためのいくつかのステートメン トがあります。サポートされているフロー制御ステートメントのいくつかを以下にリストします: CASE (単純な条件で実行パスを選択する) 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 97 IF FOR (表の各行に対して ステートメントのグループ を実行する) WHILE ITERATE (次の繰り返しを強制する。C 言語の CONTINUE と同等) LEAVE (ブロックまたはループから抜ける。”構造化された Goto” ) LOOP (無限ループ) REPEAT GOTO RETURN CALL (プロシージャー呼び出し) 3.3.10 エラーおよび条件ハンドラー DB2 では、SQL ステートメントが正常に実行できたか失敗したかを判定するために、SQLCODE および SQLSTATE キーワードが使用されます。これらのキーワードは、以下のようにプロシージャ ーの最も外側のスコープで明示的に宣言しておく必要があります: DECLARE SQLSTATE CHAR(5); DECLARE SQLCODE INT; DB2 は各 SQL 処理の後に上記のキーワードに自動的に値を設定します。SQLCODE に対して は、以下のように値が設定されます: = 0, 成功 > 0, 警告つき成功 < 0, 失敗 = 100, データが見つからない。 (i.e.: FETCH ステートメントがデータを戻さなかった。) SQLSTATE に対しては、以下のように値が設定されます: 成功: SQLSTATE '00000 見つからない: SQLSTATE '02000' 警告: SQLSTATE '01XXX' 例外: その他の値 98 DB2 アプリケーション開発入門 SQLCODE は RDBMS 固有で、 SQLSTATE よりも詳細です。SQLSTATE は、RDMBS の標 準ですが、非常に曖昧な情報です。いくつかの SQLCODE が一つの SQLSTATE に合致する場 合もあります。 SQL ステートメントによって、ある条件が引き起こされ、それがある SQLSTATE に合致することが あります。例えば、SQL 処理の途中で値が切り捨てられた場合には、SQLSTATE '01004' のよう に特定の条件が引き起こされます。この条件をテストするために SQLSTATE '01004' を使うので はなく、名前を割り当てることができます。この例では、以下のように SQLSTATE ‘01004’ という条 件に対して、trunc という名前を割り当てることができます。 DECLARE trunc CONDITION FOR SQLSTATE '01004' その他の事前定義済みの一般的な条件には以下のものがあります: SQLWARNING SQLEXCEPTION NOT FOUND 3.3.10.1 条件ハンドリング 条件をハンドルするには、以下を指定して条件ハンドラーを作成します: どの条件をハンドルするか どこで処理の実行を再開するか (ハンドラーのタイプに基づく: CONTINUE,、EXIT または UNDO) 条件をハンドルするのに、どのアクションを実行するか。アクションは、制御構造を含め、ど のようなステートメントでもよい。 SQLEXCEPTION が発生し、ハンドラーがない場合には、プロシージャーは終了し、クライアント にエラーが戻ります。 3.3.10.2 ハンドラーのタイプ ハンドラーには 3 つのタイプがあります: CONTINUE – このハンドラーは、例外が発生した後、ハンドラーが条件をハンドルする際 に、条件が発生したステートメントの次のステートメントの実行をフローが続けることを示す 場合に使われます。 EXIT – このハンドラーは、例外が発生した後、ハンドラーが条件をハンドルする際に、フロ ーがプロシージャーの終わりに行くことを示す場合に使われます。 UNDO – このハンドラーは、例外が発生した後、ハンドラーが条件をハンドルする際に、フ ローがプロシージャーの終わりに行き、実行されたステートメントを取り消しまたはロールバ ックすることを示す場合に使われます。 図 3.10 で、各条件ハンドラーとその挙動を示しています。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 99 図 3.10 – 条件ハンドラーのタイプ 3.3.11 ストアード・プロシージャーの呼び出し リスト 3.5, 3.6 および 3.7 の以下のコードの抜粋は、それぞれ CLI/ODBC、VB.NET および Java プログラムからストアード・プロシージャーを呼び出す方法を示しています。 SQLCHAR *stmt = (SQLCHAR *) "CALL MEDIAN_RESULT_SET( ? )" ; SQLDOUBLE sal = 20000.0; /* Bound to parameter marker in stmt */ SQLINTEGER salind = 0; /* Indicator variable for sal */ sqlrc = SQLPrepare(hstmt, stmt, SQL_NTS); sqlrc = SQLBindParameter(hstmt, 1, SQL_PARAM_OUTPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &sal, 0, &salind); SQLExecute(hstmt); if (salind == SQL_NULL_DATA) printf("Median Salary = NULL\n"); else printf("Median Salary = %.2f\n\n", sal ); /* Get first result set */ sqlrc = StmtResultPrint(hstmt); /* Check for another result set */ sqlrc = SQLMoreResults(hstmt); if (sqlrc == SQL_SUCCESS) { /* There is another result set */ sqlrc = StmtResultPrint(hstmt); } リスト 3.5 - CLI/ODBC アプリケーションからストアード・プロシージャーを呼び出す例 100 DB2 アプリケーション開発入門 よ り 詳 細 に つ い て は 、 DB2 の サ ン プ ル ・ フ ァ イ ル を 参 照 し て 下 さ い : sqllib/samples/sqlproc/rsultset.c Try ‘ Create a DB2Command to run the stored procedure Dim procName As String = “TRUNC_DEMO” Dim cmd As DB2Command = conn.CreateCommand() Dim parm As DB2Parameter cmd.CommandType = CommandType.StoredProcedure cmd.CommandText = procName ‘ Register the output parameters for the DB2Command parm = cmd.Parameters.Add(“v_lastname”, DB2Type.VarChar) parm.Direction = ParameterDirection.Output parm = cmd.Parameters.Add(“v_msg”, DB2Type.VarChar) parm.Direction = ParameterDirection.Output ‘ Call the stored procedure Dim reader As DB2DataReader = cmd.ExecuteReader Catch myException As DB2Exception DB2ExceptionHandler(myException) Catch UnhandledExceptionHandler() End Try リスト 3.6 - VB.NET アプリケーションからストアード・プロシージャーを呼び出す例 try { // Connect to sample database String url = “jdbc:db2:sample”; con = DriverManager.getConnection(url); CallableStatement cs = con.prepareCall(“CALL trunc_demo(?, ?)”); // register the output parameters callStmt.registerOutParameter(1, Types.VARCHAR); callStmt.registerOutParameter(2, Types.VARCHAR); cs.execute(); con.close(); 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 101 } catch (Exception e) { /* exception handling logic goes here */ } リスト 3.7 – Java アプリケーションからストアード・プロシージャーを呼び出す例 3.3.12 動的 SQL 動的 SQL では、静的 SQL とは反対に、SQL ステートメントの全体は実行時には分かっていませ ん。例えば、もし以下のステートメントの col1 と tabname が変数であった場合、これは動的 SQL です: 'SELECT ' || col1 || ' FROM ' || tabname; 依存の問題とパッケージの無効化を避けるために、DDL では動的 SQL を使用することが推奨さ れています。また、再帰の実装のためにも必要です。 動的 SQL は、二つの方法で実行することができます: EXECUTE IMMEDIATE ステートメントを使用する – これは一度だけ実行する SQL の場 合に望ましい方法です。 EXECUTE ステートメントと共に PREPARE ステートメントを使用する – これは複数回実 行する SQL の場合に望ましい方法です。 リスト 3.8 のコードの抜粋は、二つの方法を使用した動的 SQL の例を示しています。この例では、 表 T2 が以下の定義で作成されていることを前提としています: CREATE TABLE T2 (c1 INT, c2 INT) CREATE PROCEDURE dyn1 (IN value1 INT, IN value2 INT) SPECIFIC dyn1 BEGIN DECLARE stmt varchar(255); DECLARE st STATEMENT; SET stmt = 'INSERT INTO T2 VALUES (?, ?)'; PREPARE st FROM stmt; EXECUTE st USING value1, value1; EXECUTE st USING value2, value2; 102 DB2 アプリケーション開発入門 SET stmt = INSERT INTO T2 VALUES (9,9)'; EXECUTE IMMEDIATE stmt; END リスト 3.8 – 動的 SQL を使用したストアード・プロシージャーの例 3.4 Java ストアード・プロシージャー DB2 の Java ストアード・プロシージャーは、プロシージャーの定義と外部の Java アプリケーショ ンを示す CREATE PROCEDURE ステートメントを使用して作成します。Java ストアード・プロシ ージャーは IBM Data Studio を使用して簡単に作成することができます。3.2 節で示した手順と 同じ手順に従い、言語として Java を選択します。IBM Data Studio では、プロシージャーに JDBC を使用するか SQLJ を使用するかも選択することができます。Java ストアード・プロシージ ャー作成時に全てデフォルトの設定を使用すると、対応する Java アプリケーションが作成されま す。図 3.11 で Java ストアード・プロシージャーを作成時の IBM Data Studio を示しています。図 3.12 では、対応する Java のソース・コードを示しています。 図 3.11 – Java ストアード・プロシージャー用の CREATE PROCEDURE の定義 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 103 図 3.12 - Java ストアード・プロシージャー用の Java ソース・コード 3.5 ユーザー定義関数: 概要 ユーザー定義関数 (UDF) は、入力データの値を出力の値にマップするデータベース・アプリケー ション・オブジェクトです。例えば、インチ単位の計測値を入力し、センチメートル単位にして戻すよ うな関数が挙げられます。 DB2 は、SQL PL、PL/SQL、C/C++、Java、CLR (共通言語ランタイム) および OLE (Object Linking and Embedding) を使用した関数の作成をサポートしています。本書では、簡便性や 人気、パフォーマンスなどの理由から、SQL PL に着目します。 注: DB2 9.7 より前のバージョンでは、UDF はインライン SQL PL として知られる SQL PL ステートメ ントのサブセットのみをサポートしていました。DB2 9.7 では、全ての SQL PL ステートメントが完 全にサポートされています。 注: 104 DB2 アプリケーション開発入門 UDF に関するより詳細な情報については、以下のビデオを参照してください: http://www.channeldb2.com/video/video/show?id=807741:Video:4362 ユーザー定義関数には四つのタイプの関数があります: スカラー関数、表関数、行関数、列関数 です。本書では、スカラー関数と表関数のみに着目します。 3.5.1 スカラー関数 スカラー関数は、単一の値を戻します。スカラー関数はデータベースの状態を変更するような SQL ステートメントを含むことはできません; つまり、INSERT、UPDATE、DELETE ステートメント の使用は許可されていません。SUM()、AVG()、DIGITS()、COALESCE()、SUBSTR() などの組 み込みスカラー関数があります。 DB2 では、カスタマイズされたユーザー定義関数を作成することができ、頻繁に使用されるロジッ クをカプセル化することができます。リスト 3.9 でスカラー関数の例を示します。 CREATE FUNCTION deptname(p_empid VARCHAR(6)) RETURNS VARCHAR(30) SPECIFIC deptname BEGIN ATOMIC DECLARE v_department_name VARCHAR(30); DECLARE v_err VARCHAR(70); SET v_department_name = ( SELECT d.deptname FROM department d, employee e WHERE e.workdept=d.deptno AND e.empno= p_empid); SET v_err = 'Error: employee ' || p_empid || ' was not found'; IF v_department_name IS NULL THEN SIGNAL SQLSTATE '80000' SET MESSAGE_TEXT=v_err; END IF; RETURN v_department_name; END リスト 3.9 – スカラー関数の例 上記のリストでは、関数の名前は deptname であり、社員 ID に基づいて社員の部門番号を戻し ます。スカラー・ユーザー定義関数 は VALUES ステートメントを使用して呼び出すことができます。 また、スカラー値が期待される SQL ステートメントからも呼び出すことが可能です。例えば、Linux または UNIX 端末の DB2 コマンド・ウィンドウから以下を実行してみてください: db2 "values (deptname ('000300'))" または db2 "select (deptname ('000300')) from sysibm.sysdummy1" 二つ目の例で SYSIBM.SYSDUMMY1 が使用されていることに注意してください。これは一つの 行と一つの列を持つ特別なダミー表です。これは一つの値のみが返されることを保証するために 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 105 使用されます。もし、より多くの行を持つ他の表に対して同じ SELECT ステートメントを実行した場 合、その表に含まれる行の数と同じ回数だけ関数が実行されます。 3.5.2 表関数 表関数は、表を戻します。ステートメントの FROM 節を使用して呼び出すことができます。表関数 はスカラー関数とは異なり、データベースの状態を変更することができます; そのため、INSERT、 UPDATE、DELETE ステートメントの使用が許可されています。SNAPSHOT_DYN_SQL( ) や MQREADALL( ) など、いくつかの組み込み表関数があります。表関数はビューと似ていますが、 データを変更するステートメント (INSERT、UPDATE、DELETE) が許可されているため、より強力 です。一般的に、表を戻し、監査レコードを保持するために使用されます。 リスト 3.10 では、部門社員を列挙する表関数の例を示しています。 CREATE FUNCTION getEnumEmployee(p_dept VARCHAR(3)) RETURNS TABLE (empno CHAR(6), lastname VARCHAR(15), firstnme VARCHAR(12)) SPECIFIC getEnumEmployee RETURN SELECT e.empno, e.lastname, e.firstnme FROM employee e WHERE e.workdept=p_dept リスト 3.10 – 表関数の例 上記の関数をテストするために、以下の図 3.13 で示した SELECT ステートメントを実行してみて ください。 図 3.13 – 表関数の呼び出し 上記の図で示されているように、表ユーザー定義関数は表を戻すため、SQL ステートメントの FROM 節から呼び出さなければなりません。TABLE() という特殊な関数を併せて使用し、呼び出 しの後にエイリアスを指定する必要があります。 106 DB2 アプリケーション開発入門 3.6 トリガー: 概要 トリガーは、表に対して INSERT、UPDATE または DELETE 処理が実行された際の処理内容を 定義する、表に関連付けられたデータベース・オブジェクトです。トリガーは自動的に起動されます。 トリガーを起動する処理は、トリガーとなる SQL ステートメントと呼ばれます。 注: トリガーに関するより詳細な情報については、以下のビデオを参照してください: http://www.channeldb2.com/video/video/show?id=807741:Video:4367 注: DB2 9.7 より前のバージョンでは、トリガーはインライン SQL PL として知られる SQL PL ステートメ ントのサブセットのみをサポートしていました。DB2 9.7 では、全ての SQL PL ステートメントが完 全にサポートされています。 3.6.1 トリガーのタイプ トリガーには三つのタイプがあります: “before” トリガー、“after” トリガー、“instead of” トリガーです。 3.6.1.1 Before トリガー before トリガーは行が挿入、更新、削除される前に起動されます。このトリガーによって実行される 処理は、他のトリガーを起動することはできません; そのため、INSERT、UPDATE、DELETE 処 理は許可されていません。構文の説明を含む簡単な before トリガーの例を図 3.14 で示していま す。 図 3.14 –before トリガーの例 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 107 上 記 の 図 で は 、 CL_SCHED 表 で INSERT SQL ス テ ー ト メ ン ト が 実 行 さ れ る 前 に default_class_end というトリガーが実行されます。この表は SAMPLE データベースに含まれる ので、このデータベースに接続した状態で、このトリガーをテストすることが可能です。トリガーの定 義にある n という変数は、INSERT による新しい値を示しています。つまり、挿入される値です。トリ ガーは表に挿入されるデータの妥当性を確認します。もし INSERT 処理で ENDING 列に値がな かった場合には、トリガーは STARTING 列の値に一時間足した値がそこに入るように保証します。 リスト 3.11 は、トリガーのテストに使用できるステートメントと、対応する出力を示しています。 C:\Program Files\IBM\SQLLIB\BIN>db2 insert into cl_sched (class_code, day, starting) values ('abc',1,current time) DB20000I The SQL command completed successfully. C:\Program Files\IBM\SQLLIB\BIN>db2 select * from cl_sched CLASS_CODE DAY STARTING ENDING ---------- ------ -------- -------042:BF 4 12:10:00 14:00:00 553:MJA 1 10:30:00 11:00:00 543:CWM 3 09:10:00 10:30:00 778:RES 2 12:10:00 14:00:00 044:HD 3 17:12:30 18:00:00 abc 1 11:06:53 12:06:53 6 record(s) selected. リスト 3.11 - 作成した before トリガーのテスト 上記のリストでは、INSERT ステートメントの中で ENDING 列に値が渡されていないことがわかりま す; そのため、その値は NULL になります。また、CURRENT TIME は、起動された時刻を戻す DB2 の特殊レジスターです。この例では、現在の時刻は 11:06:53 なので、この値が STARTING 列に割り当てられ、ENDING 列にはトリガーのロジックが割り当てる値が入るため、11:06:53 に一 時間足した値になります。 以 下 に 示 す validate_sched ト リ ガ ー は 、 追 加 の 条 件 を 加 え る こ と に よ り 、 前 述 の default_class_end トリガーの機能を拡張しています。 CREATE TRIGGER validate_sched NO CASCADE BEFORE INSERT ON cl_sched REFERENCING NEW AS n FOR EACH ROW MODE DB2SQL BEGIN ATOMIC -- supply default value for ending time if null IF (n.ending IS NULL) THEN SET n.ending = n.starting + 1 HOUR; 108 DB2 アプリケーション開発入門 END IF; -- ensure that class does not end beyond 9pm IF (n.ending > '21:00') THEN SIGNAL SQLSTATE '80000' SET MESSAGE_TEXT='class ending time is beyond 9pm'; ELSEIF (n.DAY=1 or n.DAY=7) THEN SIGNAL SQLSTATE '80001' SET MESSAGE_TEXT='class cannot be scheduled on a weekend'; END IF; END リスト 3.12 – 作成した before トリガーの拡張 3.6.1.2 After トリガー after トリガーは、トリガーとなる SQL ステートメントが正常に終了した後に起動されます。このトリガ ーによって実行される処理は、他のトリガーを起動することもあります。(16 段階までカスケードが許 可されています。) after トリガーは INSERT、UPDATE、DELETE 処理をサポートしています。リ スト 3.13 は after トリガーの例を示しています。 CREATE TRIGGER audit_emp_sal AFTER UPDATE OF salary ON employee REFERENCING OLD AS o NEW AS n FOR EACH ROW MODE DB2SQL INSERT INTO audit VALUES ( CURRENT TIMESTAMP, ' Employee ' || o.empno || ' salary changed from ' || CHAR(o.salary) || ' to ' || CHAR(n.salary) || ' by ' || USER) リスト 3.13 - after trigger の例 上記のリストでは、EMPLOYEE 表の SALARY 列を監査するために audit_emp_sal というトリガ ーが使用されています。ある人がこの列に変更を加えた場合、給与に対する変更の情報を AUDIT という別の表に書き込むためにトリガーが起動されます。OLD as o NEW as n という行は、表 の中の古い値や既存の値を示すために接頭辞 o が使用され、UPDATE ステートメントによる新しい値 を示すために接頭辞 n が使用されることを示します。従って、o.salary は給与の古い、または既 存の値を示し、n.salary は 給与データの更新された列の値を示します。 3.6.1.3 “Instead of” トリガー instead of トリガーは、ビューに定義されます。ビューは一つまたは二つ以上の表にアクセスする SELECT ステートメントによって動的に定義されるため、ビューは更新することができません。しか し、このタイプのトリガーを使用すると、起動させる SQL ステートメントの代わりにトリガー内で定義 されたロジックが実行されるため、ユーザーに対してビューを更新することができるような錯覚を与 えることができます。例えば、ビューに対して更新処理を実行した場合、そのビューを構成している 基礎表に対して実際に更新処理を実行するために instead of トリガーが起動されます。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 109 トリガーは IBM Data Studio から作成することはできません。コントロール・センターまたはコマンド 行ツール (DB2 コマンド・ウィンドウ、コマンド行プロセッサーまたはコマンド・エディター) で作成す ることができます。 3.7 Data Web サービス Data Web サービスは、データベースの情報に基づいた Web サービスです。IBM Data Studio を使用すると、非常に簡単に Data Web サービスを作成することができます。Web サービスは、 JEE アプリケーション (以前の J2EE) に似ています; そのため、Web サービスはアプリケーション・ サーバー上にデプロイする必要があります。本書では、Apache Geronimo をベースとした無償の アプリケーション・サーバーである WebSphere Application Server Community Edition (WAS CE) バージョン 2.1 を使用します。WAS CE は以下のサイトからダウンロード可能です: http://www.ibm.com/developerworks/downloads/ws/wasce/ WAS CE はサイズが小さく、非常に簡単にインストールできます。Data Web サービスを使う前に WAS CE をインストールしておいてください。 注: WAS CE に関するより詳細な情報については、DB2 on Campus の無償の eBook シリーズの一 部である Getting started with WAS CE という eBook を参照してください。 Data Studio から Data Web サービスを作るには、新規プロジェクトを開くか作成し、Web サービ ス フォルダーを選択してください。このフォルダーを右クリックし、新規 Web サービス を選択してく ださい。Web サービスに名前をつけ、 終了 をクリックします。 図 3.15 でこの手順で作成した MyWebService を示しています。 110 DB2 アプリケーション開発入門 図 3.15 – Data Web サービスの作成 ここまでで Web サービスは作成しましたが、現時点ではこの Web サービスにはメソッドや処理は ありません。Web サービスに処理を追加するには、Data Studio であらかじめ作成しておいたスト アード・プロシージャーや SQL スクリプトをドラッグ・アンド・ドロップすればよいだけです。例えば、 以下の図 3.16 を見てください。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 111 図 3.16 – Data Web サービスの処理を作成するためのドラッグ・アンド・ドロップ 上記の図は SELECT * FROM EMPLOYEE ステートメントを元にしたカーソルを戻す、GETALLEMP と いうストアード・プロシージャーを示しています。このプロシージャーがデプロイされ、テストされた後、 図でハイライトされている MyWebService という Web サービスにドラッグ・アンド・ドロップすること によって、Web サービスの処理として追加されます。以前作成した SQL スクリプトや、既にデータ ベースにデプロイされ、データ・ソース・エクスプローラーから確認できるストアード・プロシージャー についても、同様の手順を実行することができます。 Web サービスに少なくとも一つ以上の処理がある場合、以下の 図 3.17 で示したように、その Web サービスを選択し、右クリックして ビルドおよびデプロイ を選択することによって、それをビル ドしてデプロイすることができます。 112 DB2 アプリケーション開発入門 図 3.17 – data web サービスのビルドとデプロイ ビルドおよびデプロイ を選択した後、図 3.18 にあるように Web サービスのデプロイ ウィンドウが 表示されます。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 113 図 3.18 –Web サービスのデプロイ ウィンドウ ここでは、Web サービスのデプロイ ウィンドウの Web サーバー セクションの タイプ フィールドで WAS CE 2.1 を選択します。その他のサポートされているアプリケーション・サーバーには、 Apache Tomcat と WebSphere Application Server (WAS) があります。ここでは DB2 データ・ サーバーと同じコンピューター上に既に WAS CE がインストールされているので、オプションとし ては デプロイ可能ファイルのビルドのみ、Web サーバーにデプロイしない ではなく、サーバー を 114 DB2 アプリケーション開発入門 選択します。この二つ目のオプションは、WAR ファイルを作成し、それを後ほど Web サービスを デプロイしたいアプリケーション・サーバーに転送します。上記の図 3.18 では、アプリケーション・ サーバーが既に IBM Data Studio 上に追加されています。もし追加されていない場合には、 新 規 ボタンを押し、ほとんどのパネルでデフォルト値を指定してください。一つ指定しなければいけ ないのは、 WAS CE のインストール先です。Windows でのデフォルトのインストール・パスは以下 の通りです: C:\Program Files\IBM\WebSphere\AppServerCommunityEdition Web サービスのデプロイ ウィンドウに戻り、デプロイメント後に Web サービス・エクスプローラーを 起動 チェックボックスをクリックし、終了 をクリックしてください。この時点で、WAS CE が起動され、 Data Web サービスがデプロイされます。これには約 10 秒から 20 秒かかります。終了後、Web サービス・エクスプローラーが起動されます。図 3.19 で Web サービス・エクスプローラーを示して います。 図 3.19 – Web サービス・エクスプローラー 上記の図では、Web サービス・エクスプローラーの左側のパネルに Web サービス記述言語 (WSDL) がどこにあるかを示す URL で始まるツリーがあります。この例では、WSDL は以下の場 所にあります: http://localhost:8080/MyProjectmyWebService/wsdl ツリーは以下の三つの項目も示します: 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 115 myWebServiceHTTPGET myWebServiceHTTPPOST myWebServiceSOAP 最初の二つの項目は REST プロトコルに対応しており、最後の一つは SOAP プロトコルに対応し ています。図 3.18 の メッセージ・プロトコル セクションでは、REST プロトコルと SOAP プロトコル の両方にチェックを入れていました。両方のタイプの Web サービスが作成されていたのはこのた めです。REST と SOAP は Web サービスで使用できる二つの標準的なプロトコルであり、使いた い方を選択することができます。IBM Data Studio はこれらのうち片方を使っても、両方を使っても Web サービスを作成することができます。図 3.19 では、SOAP バージョンの GETALLEMP メソッ ドがハイライトされており、右側のパネルの Go をクリックすると、このメソッドをテストすることができ ます。出力は右側下段のパネルに Form として表示されます。図 3.19 では、出力を Source とし て表示しています。 REST バージョンの GETALLEMP メソッドをブラウザーから呼び出したい場合には、まずどのよう にメソッドを呼び出すかを確認するために WSDL を見てください。WSDL をスクロール・ダウンす ると、メソッドの呼び出し方がわかります。これは図 3.20 で示されています。 図 3.20 – WSDL 116 DB2 アプリケーション開発入門 上記の図では、Web サービスを呼び出す際に使用される URL をハイライトしています。この URL には、実行したいメソッドの名前を追加する必要があります。この例での URL の全体は以下のよう になります: http://localhost:8080/MyProjectmyWebService/rest/myWebService/GETALLEMP メソッドの名前は大文字小文字を区別することに注意してください。図 3.21 では、上記の URL を ブラウザーに入力した場合の出力を示しています。 図 3.21 – myWebService からの GETALLEMP メソッドの呼び出し 希望する場合には、この XML の出力に XSLT を適用することもできます。これは図 3.22 で示さ れているように、Data Studio で Data Web サービスのメソッドを右クリックし、XSLT の管理 を選 択することにより実行できます。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 117 図 3.22 – Web サービスのメソッドの出力への XSLT の適用 XSL トランスフォーメーションの構成 ウィンドウで、参照 をクリックし、事前に作成した XSL ファイ ルを選択してください。例えば、リスト 3.14 はこの例で使用した XSL ファイルの一部を示していま す。 118 DB2 アプリケーション開発入門 リスト 3.14 - Data Web サービスの例で使用した XSL ファイル 図 3.23 で、この XSL ファイルをどのように指定するかを示しています。 図 3.23 – 使用する XSL ファイルの指定 終了 をクリックした後、Web サービスを再びビルドし、デプロイする必要があります。そして、 図 3.21 と同じ URL でブラウザーを更新すると、図 3.24 に示した出力が得られます。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 119 図 3.24 – GETALLEMP メソッドを XSLT を使用して呼び出した場合の出力 注: この Data Web サービスの例に関する全てのデモについては、以下のビデオを参照してください: http://www.channeldb2.com/video/video/show?id=807741%3AVideo%3A1482 3.8 演習 この演習では、IBM Data Studio を使用してスカラー・ユーザー定義関数 を作成します。これによ り、Data Studio についてより多くの経験をすることができ、ユーザー定義関数の SQL PL にも慣 れることができます。 手順 1. IBM Data Studio を開きます。 (ヒント: スタートメニューから開けます。). 2. この章で以前説明されていた手順で、第 5 章で作成した EXPRESS データベースに関 連づいた新規プロジェクトを作成します。そして、ユーザー定義関数 フォルダーが見える までドリルダウンします。 3. ユーザー定義関数 フォルダーを右クリックし、新規 -> ユーザー定義関数 を選択します。 120 DB2 アプリケーション開発入門 4. SQL PL ユーザー定義関数を作成するので、関数の名前として booktitle を指定し、言 語として SQL を選択します。 5. ここで、次へ ボタンを数回クリックし、UDF の作成が完了するまで全てデフォルト値を使 用します。あるいは、この時点で 終了 ボタンをクリックします。 6. サンプル・コードが表示された編集ウィンドウが立ち上がります。コードを全て消去し、以 下のものと置き換えます。 CREATE FUNCTION booktitle(p_bid INTEGER) RETURNS VARCHAR(300) ---------------------------------------------------------SQL UDF (Scalar) ---------------------------------------------------------SPECIFIC booktitle F1: BEGIN ATOMIC DECLARE v_book_title VARCHAR(300); DECLARE v_err VARCHAR(70); SET v_book_title = (SELECT title FROM books WHERE p_bid = book_id); SET v_err = 'Error: The book with ID ' || CHAR(p_bid) || ' was not found.'; IF v_book_title IS NULL THEN SIGNAL SQLSTATE '80000' SET MESSAGE_TEXT=v_err; END IF; RETURN v_book_title; END 7. 関数名を右クリックして デプロイ を選択し、デプロイ・オプション パネルで 終了 を選択し て関数をビルドします。 8. 関数名を右クリックし、実行 を選択して関数を実行します。 9. この関数は入力パラメーターを一つ取るため、パラメーターの値を入力するためのダイア ログ・ウィンドウが表示されます。 以下の値を入力してください: 80002 結果はどうなりましたか? 次の値でもう一度実行してください: 1002 今度はどうなりましたか? (ヒント: SQL 結果 タブを見てください。) 10. 終了したら、IBM Data Studio を閉じてください。 第 3 章 – ストアード・プロシージャー、ユーザー定義関数、トリガー、Data Web サービス. 121 3.9 まとめ 本章では、データ・サーバー・サイドでの開発について紹介しました。ストアード・プロシージャー、 UDF、トリガーの作成方法について論じました。SQL PL 言語と IBM Data Studio の使用を中心 に学びました。また、SQL スクリプトやストアード・プロシージャーを基にした Data Web サービスの 作成方法についてもお話しました。 3.10 確認問題 1. ストアード・プロシージャーの利点は何ですか? 2. スカラー・ユーザー定義関数 は監査情報を表に書き込むために使用できますか? 3. スカラー・ユーザー定義関数 はどのようにして呼び出すことができますか? 4. BEFORE トリガーは表を更新するために使用できますか? 5. ストアード・プロシージャーの中で、SPECIFIC キーワードは何のために使用しますか? 6. 以下のうち、トリガーのタイプとして正しくないのはどれですか? A. BEFORE B. PRESENT C. AFTER D. INSTEAD OF E. None of the above 7. 以下のツールのうち、トリガーの作成に使用できるのはどれですか? A. Control Center B. Command Editor C. DB2 Command Window D. IBM Data Studio E. None of the above 8. 以下のステートメントのうち、getFlights 表関数を正しく呼び出すことができるのはどれで すか? A. SELECT * FROM GETFLIGHTS() B. SELECT * FROM GETFLIGHTS C. SELECT * FROM TABLE (GETFLIGHTS) A D. SELECT * FROM TABLE (GETFLIGHTS) AS A E. C と D 9. 以下の文章のうち、正しいのはどれですか? 122 DB2 アプリケーション開発入門 A. WSDL は Web サービス記述リストの略です。 B. SOAP および REST Web サービスはどちらも内部で XML を使用しています 。 C. デプロイされたストアード・プロシージャーは、Data Studio 上の Web サービ スに対して新しいメソッドを作成するために、その Web サービスにドラッグ ・アンド・ドロップすることはできません。 D. A と C です。 E. 上記のどれでもありません。 10. 以下の文章のうち、正しくないのはどれですか? A. DB2 のストアード・プロシージャーは C/C++ 言語を使用して開発することが できます。 B. ユーザー定義関数は、インライン SQL PL として知られる SQL PL 言語のサ ブセットのみをサポートしています。 C. ストアード・プロシージャーはユーザー定義関数を呼び出すことができます。 D. トリガーはストアード・プロシージャーを呼び出すことができます。 E. 上記のどれでもありません。 4 第 4 章 – Java によるアプリケーション開発 この章では、Java と DB2 を使ってアプリケーションを開発する際の基礎についてご説明します。 Java アプリケーションの多くは Java Database Connectivity (JDBC)を使った動的 SQL や、 SQLJ を使った静的 SQL でデータベースへアクセスします。これらは、ベンダーに依存せずに Java で記述されたクラスとインターフェースの集合です。 この章では、以下の点をご説明します。 JDBC を使ったプログラミング SQLJ を使ったプログラミング pureQuery を使ったプログラミング 4.1 Java - DB2 アプリケーション: 全体像 データベースへアクセスする Java アプリケーションを開発する時には、標準規格である JDBC か SQLJ を使います。この標準規格のサポートは、ベンダーが提供する JDBC ドライバーや SQLJ ドライバーにより提供されます。 図 4.1 では、DB2 データ・サーバーを利用する場合の例を説明 しています。 図 4.1 - DB2 データベースにアクセスする Java アプリケーション この図では、Java アプリケーションは JDBC/SQLJ ドライバーを通して DB2 データ・サーバーへ 接続しています。接続が成功した後、Java アプリケーションから実行された SQL や XQuery ステ 124 DB2 アプリケーション開発入門 ートメントが DB2 データ・サーバーに送られ、処理された結果が Java アプリケーションに戻りま す。 アプリケーションで JDBC と SQLJ を利用すれば、データ・サーバーの変更の際も、JDBC/SQLJ の仕様に則した他のデータベース (例えば DB2 や Informix 、Oracle、SQL Server など) への変 更であれば、アプリケーションの変更を最小限に抑えることができます。DB2 9.7 は JDBC 4.0 も しくはそれ以前の JDBC の仕様をサポートしています。 DB2 では、JDBC と SQLJ のドライバーは以下のいずれかに含まれています。 全てのエディションの DB2 Data Server IBM Data Server Client IBM Data Server Runtime Client IBM Data Server Driver for JDBC and SQLJ データ・サーバーのエディション、クライアント、ドライバーに関しては、第 1 章 DB2 アプリケーショ ン開発の概要 で説明されています。アプリケーションで利用する JDBC ドライバーのタイプによっ ては、クライアントのインストールが必要な場合があります。JDBC ドライバーのタイプの違いについ ては、次の節で説明します。 4.2 環境の準備 JDBC や SQLJ のアプリケーションを実行、もしくは開発する前に、環境が正しく準備されているか 確認してください。 サーバーに配置する Java ストアード・プロシージャーや Java ユーザー定義関数を開発する場 合、DB2 サーバーに JDK がインストールされているか確認してください。幸い、DB2 バージョン 9.7 をインストールした時には、IBM SDK for Java 6 (別称 JDK 6) が全てのプラットフォームにお いてデフォルトでインストールされます。インストールされる場所はデータベース・マネージャー構 成パラメーター (dbm cfg) の JDK_PATH で設定されます。例えば、Windows のデフォルトの パスは C:\Program Files\IBM\SQLLIB\java\jdk です。Java ストアード・プロシージャーや Java ユーザー定義関数をコンパイルする際は、このパスにある Java コンパイラー (javac) を利用でき ます。 DB2 サーバーで JDBC/SQLJ アプリケーションを開発する場合、JDBC/SQLJ ドライバーが正しく 利用できるよう CLASSPATH に正しい jar ファイルが含まれているか、確認してください。同様 に、クライアント・マシンで JDBC/SQLJ アプリケーションを開発する場合、JDBC/SQLJ ドライバー が正しくインストール、設定されているか、確認してください。JDBC タイプ 2 ドライバーを利用して いる場合、DB2 クライアント (IBM Data Server Client か IBM Data Server Runtime Client のい ずれか) もインストールする必要があります。詳しくは次の節で説明します。 第 4 章 – Java によるアプリケーション開発 125 4.2.1 DB2 JDBC ドライバーと SQLJ ドライバー 表 4.1 では、現在一般的に利用されている JDBC ドライバーのタイプの違いを説明しています。 タイプ ドライバー名 説明 DB2 で提供有無 タイプ 1 JDBC-ODBC ブリッジ・ ドライバー このドライバーでは、JDBC によるアク セスは ODBC ドライバー経由で実施 されます。 無し タイプ 2 ネイティブ API ドライバ ー このドライバーを利用する場合、同じ マシン上に DB2 クライアントがインス トールされている必要があります。後 述しますが、DB2 では 2 つの タイプ 2 ドライバーが提供されています。 有り タイプ 3 JDBC ネット pure Java ドライバー このドライバーでは、Java で実装され たクライアントによって、ネット・サーバ ーとデータベース独自のプロトコルで コミュニケーションを行います。ネット・ サーバーはクライアントの要求をデー タベースへ送ります。DB2 ではこのド ライバーはサポートされておらず、タ イプ 4 ドライバーが推奨されていま す。 無し タイプ 4 ネイティブ・プロトコル pure Java ドライバー このタイプが最も柔軟に利用できる JDBC API です。このドライバーは JDBC コールを DB2 で利用されるネ ットワーク・プロトコルに直接変換しま す。このタイプでは、クライアントをイ ンストールせずに直接 DB2 サーバ ーへ接続することができます。 有り 表 4.1 - JDBC ドライバーのタイプ JDBC ドライバーにはいくつかのタイプがありますが、タイプ 2 と タイプ 4 ドライバーが最もよく利 用され、パフォーマンスも優れています。そのため、DB2 9.7 では この 2 つ以外のタイプはサポ ートされていません。タイプ 2 ドライバーでは、図 4.2 で説明しているように、データベースへの接 続に DB2 クライアントが必要です。 126 DB2 アプリケーション開発入門 図 4.2 - タイプ 2 ドライバーを利用する Java アプリケーション タイプ 4 は pure Java クライアントのため DB2 クライアントは不要ですが、JDBC アプリケーション が稼働するマシン上にドライバーがインストールされている必要があります。図 4.3 は、タイプ 4 ド ライバーを利用する JDBC アプリケーションを説明しています。 図 4.3 – タイプ 4 ドライバーを利用する Java アプリケーション 表 4.2 では、DB2 JDBC ドライバー と SQLJ ドライバーについてより詳しく説明しています。 タイプ ドライバー名 ドライバー が含まれる ファイル名 サポートされる JDBC 仕様 タイプ 2 DB2 JDBC Type 2 Driver for Linux, UNIX and Windows (非推奨*) db2java.zip JDBC 1.2 JDBC 2.0 タイプ 2 とタイ プ4 IBM Data Server Driver for JDBC and SQLJ db2jcc.jar と sqlj.zip JDBC 3.0 準拠 1.4.2 db2jcc4.jar と sqlj4.zip JDBC 4.0 とそれ 以前 6 と 最低限必要な SDK for Java のレベル 1.4.2 表 4.2 - DB2 JDBC ドライバーと SQLJ ドライバー * 非推奨は、サポートはされますが今後機能拡張はされないことを意味します。 表 4.2 からわかるように、タイプ 2 は 2 つの異なるドライバーが提供されていますが、db2java.zip で提供される DB2 JDBC Type 2 Driver for Linux, UNIX and Windows は、現在は非推奨で す。 db2jcc.jar (com.ibm.db2.jcc) で提供される IBM Data Server Driver for JDBC and SQLJ で は、タイプ 2 と タイプ 4 のドライバーの両方がサポートされます。どちらのドライバーを利用するか は、Java プログラムで利用するデータベースへの接続 URL の構文 によって決まります。接続 URL にホスト名や IP アドレス、ポート番号が含まれている場合、タイプ 4 が利用されます。これら が含まれていない場合、タイプ 2 が利用されます。詳細はこの節の後述の章で説明します。IBM 第 4 章 – Java によるアプリケーション開発 127 Data Server Driver for JDBC and SQLJ は、メインフレームも含めた全てのプラットフォームの、 全ての DB2 サーバーへアクセスできるよう最適化されています。 DB2 サーバーや DB2 クライアント、 IBM Data Server Driver for JDBC and SQLJ をインストー ルした場合、JDBC 3.0 の仕様に準拠した db2jcc.jar と sqlj.zip が自動的にクラスパスに追加され ます。 JDBC 4.0 の仕様を利用したい場合、CLASSPATH 内の db2jcc.jar と sqlj.zip を、 db2jcc4.jar と sqlj4.zip にそれぞれ置き換えてください。 注: Java プログラミング言語や JVM、JRE、JDK などの概念に精通していない場合、この本と同じシリ ーズのひとつとして無償で提供されている e-book、Getting Started with Java を参照してくださ い。 4.3 JDBC プログラミング JDBC プログラムの開発は、以下のステップで構成されます。 1. JDBC タイプ 2 もしくは タイプ 4 を使ってデータベースへ接続 2. SQL ステートメントを実行 3. 結果の受け取り 4. SQL エラーと警告のハンドリング 5. 接続のクローズ これらのステップについて、次の節でより詳しく説明します。図 4.4 は、JDBC プログラムで使われ るステップ、インターフェース、クラス、メソッドの要約です。これらについても、次の節で詳しく説明 します。 128 DB2 アプリケーション開発入門 図 4.4 - JDBC プログラミングのステップ、オブジェクト、メソッド 注: この節で使われている例や図のいくつかは、IBM の Redbook である DB2 Express-C: The Developer Handbook for XML, PHP, C/C++, Java, and .NET (SG24-7301-00) から引用して います。詳しくは、この本のリソースの節をご覧ください。 4.3.1 DB2 データベースへの接続 この節では、JDBC タイプ 2 と タイプ 4 を使ってデータベースへ接続する方法を説明します。 JDBC タイプ 2 を使って接続する例として、以下のリスト 4.1 にあるコードの抜粋を見てみましょう。 (1) import java.sql.*; class myprg { public static void main (String argv[]){ try { Connection con = null; (2) Class.forName("com.ibm.db2.jcc.DB2Driver"); (3) String url = "jdbc:db2:SAMPLE"; 第 4 章 – Java によるアプリケーション開発 129 (4) if (argv.length == 2){ String userID = argv[0]; String passwd = argv[1]; con = DriverManager.getConnection(url,userID,passwd); } else {throw new Exception ("\n Usage: java myprg userID password\n"); } … リスト 4.1 - JDBC タイプ 2 を使った DB2 データベースへの接続 リスト 4.1 にある各要素について、見ていきましょう。 (1) JDBC コア API を含む java.sql パッケージをインポートします。 (2) IBM Data Server Driver for JDBC and SQLJ (db2jcc.jar/db2jcc4.jar/sqlj.zip/sqlj4.zip) からドライバー・クラスをロードします。forName メソッドは、java.sql パッケージで定義さ れたインターフェースを実装しているクラスの名前を、文字列の引数とします。この例ではク ラ ス 名 は "com.ibm.db2.jcc.DB2Driver" で す 。 db2jcc.jar フ ァ イ ル を 展 開 す る と 、 Windows 環境では以下のファイルが存在します。 C:\Program Files\IBM\SQLLIB\java\db2jcc\com\ibm\db2\jcc\DB2Driver.class 非推奨の DB2 JDBC Type 2 Driver for Linux, UNIX and Windows の場合、forName メ ソッ ド の 引 数 で 使 わ れ る ク ラ ス 名 は 、 "COM.ibm.db2.jdbc.app.DB2Driver" で す 。 db2java.zip ファイルを展開すると、Windows 環境では以下のファイルが存在します。 C:\Program Files\IBM\SQLLIB\java\db2java\COM\ibm\db2\jdbc\app\DB2Driver.class (3) URL を記述し、SAMPLE データベースに接続することを決めます。URL の構文の中に はホスト名やポート番号が含まれていません。つまり、タイプ 2 が利用されます。 タイプ 2 での接続のためには DB2 クライアントがインストールされている必要があり、DB2 クライア ントにおける SAMPLE データベースへの接続構成を利用して接続されます。 (4) 2 つの引数 (userID と passwd) がプログラムに渡された場合、これらの引数が接続のた めに使われます。引数が渡されなかった場合、プログラムは例外を投げます。 DriverManager.getConnection メソッドは、DriverManager.getConnection(url) の ように userID と passwd なしで呼ぶことも可能です。この場合、システムにログオンした ユーザー ID が利用されます。タイプ 4 では、次でご説明しているように、userID と passwd を指定しない方法は利用できません。タイプ 4 ではリモートの TCPIP 接続として 接続が行われ、リモート接続の場合、 DB2 では必ずユーザー ID と パスワードが必要とな ります。 では、リスト 4.1 と同様のコードで、JDBC タイプ 4 接続を利用しているコードの抜粋を見てみまし ょう。リスト 4.2 でご説明します。 130 DB2 アプリケーション開発入門 import java.sql.*; class myprg { public static void main (String argv[]){ try { Connection con = null; Class.forName("com.ibm.db2.jcc.DB2Driver"); (1) String url = "jdbc:db2://168.100.10.1:50000/SAMPLE"; if (argv.length == 2){ String userID = argv[0]; String passwd = argv[1]; con = DriverManager.getConnection(url,userID,passwd); } else { throw new Exception ("\n Usage: java myprg userID password\n"); } … リスト 4.2 - JDBC タイプ 4 を使った DB2 データベースへの接続 リスト 4.2 は、リスト 4.1 と同じコードですが、URL が以下のような タイプ 4 の構文を利用するもの に変更されています。 "jdbc:db2://<IP address or hostname>:<DB2 Instance port number>/<dbname>" (1) リスト 4.2 では、仮の IP アドレスとして 168.100.10.1 を利用しています。DB2 インスタン スのポート番号は 50000 で、接続するデータベース名は SAMPLE です。ネットワークに 接続していないときに接続のテストをする場合、自分のマシン自体を示す localhost か、ル ープバック IP アドレスの 127.0.0.1 が利用できます。 注: このチャプターで説明されているほとんどのコードの抜粋は、この本に付属している Exercise_Files_DB2_Application_Development.zip ファイル内の myprg.java に含まれていま す。プログラム内の適切な箇所をコメント・アウトすることで、コードの抜粋をテストすることが可能で す。 Connection オブジェクトが作成された後に、表 4.3 にある方法で、Statement、 PreparedStatement、CallableStatement オブジェクトを作成できます。 メソッド 作成されるオブジェクト 説明 第 4 章 – Java によるアプリケーション開発 131 createStatement Statement オブジェクト Statement オブジェクトでは、パラ メーター・マーカーを使わない SQL を実行できます。 prepareStatement PreparedStatement オ ブ ジェクト PreparedStatement オブジェクト では、パラメーター・マーカーを使う SQL を実行できます。 prepareCall CallableStatement オブジ ェクト CallableStatement オブジェクト では、ストアード・プロシージャーを 呼ぶことができます。 表 4.3 - Connection オブジェクトで異なるタイプの Statement オブジェクトを作成する方法 4.3.2 SQL ステートメントの実行 この節では、ホスト変数の宣言方法と、Statement、PreparedStatement、CallableStatement の インターフェースを使って SQL ステートメントを実行する方法をご説明します。 4.3.2.1 ホスト変数の宣言 ホスト変数は通常の Java の変数の規則に則しています。以下 DB2 Information Center からの 抜粋となる図 4.5 で、Java アプリケーションにおけるいくつかのデータ・タイプとデータベースのデ ータ・タイプのマッピングが示されています。 図 4.5 - Java データ・タイプと DB2 データ・タイプのマッピング 全てのマッピングのリストは以下にあります。 132 DB2 アプリケーション開発入門 http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.java.doc/ doc/rjvjdata.html DB2 では、DCLGEN (宣言生成プログラム) ユーティリティーを使ってホスト変数の構造を作成す ることができます。サポートされている言語は C、Java、COBOL、FORTRAN です。 たとえば、Java 言語で SAMPLE データベース内の employee 表の宣言文を生成するためには、 以下のように実行します。 db2dclgn -D sample -T employee -L Java 出力は employee.java ファイルに保存され、以下のリスト 4.3 のような内容となります。 … java.sql.Date hiredate; java.lang.String job; short edlevel; java.lang.String sex; java.sql.Date birthdate; java.math.BigDecimal salary; リスト 4.3 - Java 言語を使った employee 表の DCLGEN の出力 4.3.2.2 Statement インターフェース Statement インターフェースを実装しているクラスを使って、パラメーター・マーカーを含まない SQL ステートメントを実行できます。Statement オブジェクトは、Connection オブジェクトから createStatement メソッドで作成されます。 表 4.4 は、Statement オブジェクトで SQL を実行する時に利用可能ないくつかのメソッドを示し ています。 メソッド 説明 executeQuery SELECT ステートメントのように、結果セットが期待される時に利用しま す。ResultSet オブジェクトを返します。 executeUpdate INSERT、UPDATE、DELETE のように、データベースの内容を更新す る時に利用します。影響を受けた行数を Integer で返します。 execute 実行するときまでステートメントが SELECT か UPDATE かわからない時 に利用します。SQL の結果が結果セットである場合、true を返し、更新カ ウ ン ト で あ る 場 合 、 false を 返 し ま す 。 getResultSet メ ソ ッ ド や getUpdateCount メソッドと共に利用します。 表 4.4 - Statement オブジェクトのメソッド リスト 4.4 は、Statement オブジェクトと executeQuery メソッドの使い方を説明するコードの抜 粋です。 第 4 章 – Java によるアプリケーション開発 133 … (1) Statement stmt = con.createStatement(); (2) ResultSet rs = stmt.executeQuery ("SELECT EMPNO, FIRSTNME, LASTNAME " + " FROM EMPLOYEE " + " WHERE SALARY > 80000" ); (3) while ( rs.next() ) { System.out.println("Empno = " + rs.getString(1) + " Full name = " + rs.getString(2) + " " + rs.getString(3)); } (4) rs.close(); (5) stmt.close(); (6) con.close(); } catch (Exception e) { e.printStackTrace(); } }} リスト 4.4 - Statement オブジェクト: executeQuery で SELECT を実行 最初の 3 つのドットはこれがプログラムの一部であることを意味しており、リストの全ては記述されて いません。それぞれの行にマークされている数字の意味は以下の通りです。 (1) Statement オブジェクト (もしくは Statement インターフェースを実装したクラス) を使っ て、パラメーター・マーカーを含まない SQL を実行できます。Statement オブジェクトは、 Connection オブジェクトから createStatement メソッドを使って作成できます。 (2) ResultSet オブジェクトは、照会の結果セットの現在行へのカーソルを保持します。 executeQuery メソッドを使って照会 (SELECT) を実行できます。UPDATE、DELETE、 INSERT を実行する場合は、後述の executeUpdate メソッドを利用します。 (3) カーソルは、ResultSet オブジェクトの next メソッドを使うことで次の行へ進みます。デフ ォルトではカーソルは順方向のみに進み、読み取り専用です。 (4) カーソルをクローズします。 (5) ステートメントをクローズします。 (6) 接続をクローズします。 上記のコードの抜粋をテストする場合、myprg.java (本に付属) を適宜編集してください。プログラ ムはリスト 4.2 にある接続のステートメントも含んでいます。プログラムは以下のようにコンパイルし 実行してください。 javac myprg.java java myprg <userid> <password> userID が arfchong、password が mypasswd の場合、出力は、図 4.6 のようになります。 134 DB2 アプリケーション開発入門 図 4.6 - myprg.java プログラムの実行 以下のリスト 4.5 にあるコードの抜粋は、Statement オブジェクトと executeUpdate メソッドの使 い方の例です。 Statement updStmt = con.createStatement(); (1) int numRows = updStmt.executeUpdate ("UPDATE EMPLOYEE " + " SET FIRSTNME = 'Raul', " + " LASTNAME = 'Chong' " + " WHERE EMPNO = '000010' "); System.out.println("Number of rows updated " + numRows); リスト 4.5 - Statement オブジェクト: executeUpdate で UPDATE の実行 上記リストの (1) では: SQL UPDATE の操作を実行するために executeUpdate メソッドが使われ、影響を受けた行数を 整数で戻しています。上記のコード・スニペットは myprg.java の一部です。プログラムの適切な箇 所をコメント・アウトした後、以下のように実行できます。 javac myprg.java java myprg <userid> <password> 出力は以下のようになります。 Number of rows updated: 1 リスト 4.6 とリスト 4.7 は、以前のリスト 4.5 と同様の例ですが、こちらの例では、照会はまず query と 呼 ば れ る 文 字 列 と し て 保 持 さ れ 、 そ れ ぞ れ で INSERT と DELETE を 実 行 す る た め に executeUpdate メソッドを使っています。 String query = null; 第 4 章 – Java によるアプリケーション開発 135 query = "INSERT INTO employee (EMPNO, " + "FIRSTNME, LASTNAME, EDLEVEL, SALARY)" + "VALUES ('099999', 'Jin', 'Xie', 25, 90000)"; Statement stmt = con.createStatement(); int numRows = stmt.executeUpdate( query ); System.out.println("Number of rows inserted: " + numRows); stmt.close(); リスト 4.6 - Statement オブジェクト: executeUpdate で INSERT の実行 String query = null; query = "DELETE FROM employee where empno = '000999'"; Statement stmt = con.createStatement(); int numRows = stmt.executeUpdate( query ); System.out.println("Number of rows deleted: " + numRows); stmt.close(); リスト 4.7 - Statement オブジェクト: executeUpdate で DELETE の実行 次のリスト 4.8 にあるコード・スニペットは、execute メソッドを使った例です。上述のように、このメ ソッドは、実行するまで SELECT を実行するのか、UPDATE、INSERT、DELETE による更新を 実行するのか、わからない場合に利用します。 String passedStmt = "SELECT firstnme, lastname " + "FROM employee " + "WHERE salary > 80000"; Statement stmt = con.createStatement(); ResultSet rs = null; int numrows = 0; (1) if (stmt.execute(passedStmt)){ rs = stmt.getResultSet(); while ( rs.next() ) { System.out.println("Full name = " + rs.getString(1) + " " + rs.getString(2)); } rs.close(); } else { numrows = stmt.getUpdateCount(); System.out.println("Number of rows updated: " + numrows); } リスト 4.8 - Statement オブジェクト: execute で SELECT や UPDATE の実行 上記リストの (1) では: 136 DB2 アプリケーション開発入門 渡されたステートメント (この例では passedStmt) が SELECT の場合、execute メソッドは true を返します。UPDATE/INSERT/DELETE の場合、false を返します。特にこの例では渡されるス テートメントがハード・コードされていますが、引数として実装することも可能です。 このプログラムを myprg.java を使ってテストするためには、プログラム内の対応する節をコメント・ アウトして、以下のコマンドを実行してください。 javac myprg.java java myprg <userid> <password> 出力は以下のようになります。 Full name = Raul Chong Full name = MICHAEL THOMPSON Full name = SALLY KWAN Full name = JOHN GEYER Full name = EVA PULASKI Full name = EILEEN HENDERSON Full name = THEODORE SPENSER 渡されるステートメントが UPDATE の操作となるように変更した場合、プログラムをコンパイルした 後に再実行することで、以下のような結果となります。 Number of rows updated: 1 4.3.2.3 PreparedStatement インターフェース PreparedStatement インターフェースを実装したクラスを使って、パラメーター・マーカーを含む照 会を実行できます。パラメーター・マーカーは疑問符 (?) で表し、動的ステートメントの文字列内の 変数部分に置く事ができます。PreparedStatement は Statement インターフェースを継承して います。 上 述 の よ う に 、 Connection オ ブ ジ ェ ク ト の prepareStatement メ ソ ッ ド を 使 っ て 、 PreparedStatement オブジェクトを作成できます。 SQL ステートメントがパラメーター・マーカーを含む場合、ステートメントを実行する前にセッター・メ ソッドを使ってパラメーター・マーカーに値をセットする必要があります。PreparedStatement オ ブジェクトのセッター・メソッドは、”setXXX” のような名前で、 XXX はパラメーター・マーカーのデ ータ・タイプを意味しています。たとえば、setInt、setString、setDouble、setBytes、setClob、 setBlob のようになっています。 パラメーターの値をセットしたあと、SQL のタイプに応じて executeQuery や executeUpdate、 execute メソッドを使います。 リスト 4.9 は、PreparedStatement と SELECT を利用するサンプル・コードの抜粋です。 (1) PreparedStatement pStmt = con.prepareStatement 第 4 章 – Java によるアプリケーション開発 137 ("SELECT firstnme, " + " lastname " + "FROM employee WHERE salary > ? "); (2) pStmt.setInt(1,80000); (3) ResultSet rs = pStmt.executeQuery(); while ( rs.next() ) { System.out.println("Full name = " + rs.getString(1) + " " + rs.getString(2)); } (4) rs.close(); (5) pStmt.close(); リスト 4.9 - PreparedStatement オブジェクト: executeQuery で SELECT の実行 上記リストのうち、 (1) PreparedStatement が SELECT ステートメントから作られ、パラメーター・マーカー (?) が salary に使われています。 (2) salary 列は INTEGER として定義されているため、セッター・メソッドに setInt を使います。 この例では値を 80000 としてハード・コードしています。pStmt.setInt(1,80000) の “1” は、 最初のパラメーター・マーカーであることを示しています。 (3) セッター・メソッドで値をセットした後、この例では SELECT ステートメントであるため、 executeQuery を実行し、戻り値を結果セットに割り当てています。 (4) 結果セットをクローズします。 (5) PreparedStatement オブジェクトの pstmt をクローズします。 次のリスト 4.10 にあるサンプル・コードの抜粋は、前のリストと同様の例ですが、今回は UPDATE で PreparedStatement と executeUpdate を使っています。 (1) PreparedStatement pStmt = con.prepareStatement ("UPDATE employee " + " SET salary = ? " + " WHERE empno = ? "); (2) pStmt.setInt (1,85000); (3) pStmt.setString(2,"000010"); (4) int numRows = pStmt.executeUpdate(); System.out.println("Number of rows updated: " + numRows); pStmt.close(); リスト 4.10 - PreparedStatement オブジェクト: executeUpdate で UPDATE の実行 上記リストのうち、 (1) PreparedStatement が UPDATE ステートメントから作られ、パラメーター・マーカーが salary 列にひとつ、 empno 列にひとつ、使われています。 138 DB2 アプリケーション開発入門 (2) salary 列は INTEGER として定義されているため、セッター・メソッドに setInt を使います。 この例では値を 85000 としてハード・コードしています。pStmt.setInt(1,85000) の “1” は、 最初のパラメーター・マーカーであることを示しています。 (3) empno 列は文字列 (データベースでは CHAR) として定義されているため、セッター・メ ソッドに setString を使います。 (4) セッター・メソッドで値をセットしたあと、この例では UPDATE ステートメントであるため、 executeUpdate を実行し、影響を受けた行を保持します。 次の リスト 4.11 にあるサンプル・コード・スニペットは、前のリストと同様の例ですが、今回は SELECT で PreparedStatement と execute を使っています。 (1) String passedStmt = "SELECT firstnme, lastname " + "FROM employee " + "WHERE salary > ?"; PreparedStatement pStmt = con.prepareStatement(passedStmt); pStmt.setInt (1,85000); ResultSet rs = null; int numrows = 0; (2) if (pStmt.execute()) { rs = pStmt.getResultSet(); while ( rs.next() ) { System.out.println("Full name = " + rs.getString(1) + " " + rs.getString(2)); } rs.close(); } else { numrows = pStmt.getUpdateCount(); System.out.println("Number of rows updated: " + numrows); } pStmt.close(); リスト 4.11 - PreparedStatement オブジェクト: execute で SELECT の実行 上記リストのうち、 (1) PreparedStatement が SELECT ステートメントから作られ、パラメーター・マーカーが salary 列に使われています。 (2) 実行されるステートメントが 照会 (SELECT) なのか更新 (UPDATE, INSERT, DELETE) なのかわからない時は、execute メソッドを使います。渡されるステートメント (この例では passedStmt) が SELECT の 場 合 、 execute メ ソ ッ ド は true を 返 し ま す 。 UPDATE/INSERT/DELETE の場合、false を返します。特にこの例では渡されるステー トメントがハード・コードされていますが、引数として実装することも可能です。 4.3.2.4 CallableStatement インターフェース 第 4 章 – Java によるアプリケーション開発 139 CallableStatement を実装しているクラスを使って、ストアード・プロシージャーを呼ぶことができ ま す 。 CallableStatement は PreparedStatement イ ン タ ー フ ェ ー ス を 継 承 し て い ま す 。 Connection オブジェクトの prepareCall メソッドを使って CallableStatement オブジェクトを作 成できます。 CallableStatement は IN、OUT、INOUT の 3 種類のパラメーターを持つことができます。 CallableStatement を実行する前に、セッター・メソッド (setXXX) を使って IN パラメーター と INOUT パラメーターをセットする必要があります。同様に、ステートメントを実行する前に、 (registerOutParameter メソッドを使って) データベースに OUT パラメーターと INOUT パラメー ターを登録する必要があります。 CallableStatement は executeUpdate、executeQuery、execute メソッドを使って実行できま す。この 3 つのメソッドの利用方法を以下で説明します。 executeUpdate: プロシージャーの出力として結果セットが返らない時 executeQuery: プロシージャーの出力として単一の結果セットが返る時 execute: プロシージャーの出力として複数の結果セットが返る時 CallableStatement オブジェクトと executeUpdate メソッドを利用しているリスト 4.12 のサンプ ル・コードの抜粋を見てみましょう。 view_salary_increase (IN p_empno varchar(6), INOUT p_increase int, OUT p_firstname) ストアード・プロシージャーは、渡された社員番号に対応する社員のファーストネームを OUT パラ メーターとして返します。 (1) CallableStatement cstmt; (2) cstmt = con.prepareCall("call view_salary_increase(?,?,?)"); (3) cstmt.setString(1,"000010"); (4) cstmt.setInt(2,10000000); (5) cstmt.registerOutParameter(3, Types.VARCHAR); (6) cstmt.executeUpdate(); (7) System.out.println(cstmt.getString(3) + " would receive and increase of " + cstmt.getInt(2)); (8) cstmt.close(); リスト 4.12 - executeUpdate を使う CallableStatement: 結果セット無し In the above listing: 上記リストでは、以下が実行されています。 (1) CallableStatement オブジェクトの cstmt を宣言します。 (2) CallableStatement オブジェクトが Connection オブジェクトのメソッド prepareCall から 作られ、cstmt にわりあてられます。 140 DB2 アプリケーション開発入門 (3) ストアード・プロシージャーを呼び出す前に入力パラメーター (IN か INOUT) をセットして おく必要があります。 (4) 3 と同じで、このパラメーターは INOUT パラメーターです。 (5) タイプを指定するため、出力パラメーターをストアード・プロシージャーに登録しておく必要 があります。INOUT パラメーターに対して最初に setXXX を実行している場合、そのパラ メーターの登録は必須ではありません。 (6) こ の ケ ー ス で は 、 ス ト ア ー ド ・ プ ロ シ ー ジ ャ ー か ら 結 果 セ ッ ト が 返 ら な い た め 、 executeUpdate を利用します。 (7) ストアード・プロシージャー (OUT と INOUT) から情報を取得するため、getXXX メソッドを 使います。 (8) CallableStatement オブジェクト cstmt をクローズします。 次のリスト 4.13 のコードの抜粋にある例では、CallableStatement を使って、次のように定義され た high_paid_employees を呼び出します。 high_paid_employees (IN p_salary INT)) ストアード・プロシージャーは 2 つの列を持つ結果セットを返します。返される列は p_salary よりも salary が大きい社員のファースト・ネームとラスト・ネームです。 CallableStatement cstmt; (1) cstmt = con.prepareCall("call high_paid_employees(?)"); (2) cstmt.setInt(1,80000); (3) ResultSet rs = cstmt.executeQuery(); System.out.println("High-paid employees list\n" + "------------------------"); (4) while ( rs.next() ) { System.out.println( rs.getString(1) + " " + rs.getString(2) ); } rs.close(); cstmt.close(); リスト 4.13 - 単一の結果セットを返す CallableStatement 上記のリストでは、以下が実行されています。 (1) Connection オブジェクトのメソッド prepareCall から、high_paid_employees ストアー ド・プロシージャーを呼ぶための CallableStatement オブジェクト cstmt が作られます。 (2) ストアード・プロシージャーを呼び出す前に、入力パラメーターをセットします。登録する出 力パラメーターはありません。 (3) ストアード・プロシージャーが単一の結果セットを返すため、executeQuery メソッドを実行 します。 第 4 章 – Java によるアプリケーション開発 141 (4) 結果セットをループし、ゲッター・メソッド (getXXX) を使って返された結果セット内の列の 値を取得します。 4.3.3 結果の取得 このセクションでは、JDBC プログラムを作成する際の 3 番目のステップについてご説明します。 結果の取得方法として、主に ResultSet オブジェクトについてのご説明となります。 4.3.3.1 ResultSet Statement オブジェクト、PreparedStatement オブジェクト、CallableStatement オブジェクト の executeQuery メソッドによって、ResultSet オブジェクトが返されます。ResultSet オブジェク トは結果セットの現在の行へのカーソルを保持しています。カーソルはこのオブジェクトの next() メ ソッドを使うことで次の行へ移動します。カーソルはデフォルトでは、順方向のみに移動可能で読 み取り専用ですが、スクロール可能カーソルや更新可能カーソルとして定義することもできます。 現在の行の列の値は、ResultSet オブジェクトのゲッター・メソッドを呼ぶことでフェッチできます。 全ての行がフェッチされていると、next メソッドは例外を投げます。 表 4.5 は Statement オブジェクトを作成する際にセットできる ResultSet の 3 つのプロパティー をリストしています。 プロパティー 説明 resultSetType カーソルのスクロール可能性を定義する。 resultSetConcurrency カーソルの更新可能性を定義する。 resultSetHoldability ステートメントがクローズされたあとも ResultSet はオープンのままであ ることを示す。 表 4.5 - ResultSet のプロパティー createStatement と prepareStatement はこれら全てのプロパティーをサポートしており、以下 のような構文となります: createStatement (int resultSetType, resultSetConcurrency, resultSetHoldability) prepareStatement (int resultSetType, resultSetConcurrency, resultSetHoldability) これら 3 つのプロパティーは全てオプションです。以下のリスト 4.14 は、セクション 4.3 の冒頭で ふれた IBM Redbook から抜粋した ResultSet を利用する例です。 (1) Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, 142 DB2 アプリケーション開発入門 ResultSet.CONCUR_UPDATABLE); (2) ResultSet rs=stmt.executeQuery("Select POID,Status from purchaseorder"); (3) while(rs.next()) { int id = rs.getInt(1); String status = rs.getString(2); if(id==5003 && status.toUpperCase().compareTo("UNSHIPPED")==0) { System.out.println("updating status to shipped for id value "+ id+"....."); (4) rs.updateString(2,"Shipped"); (5) rs.updateRow(); } } (6) rs.beforeFirst(); System.out.println("Printing all the purchase order record status"); while(rs.next()) { int id = rs.getInt(1); String info = rs.getString(2); System.out.println("id="+id+" info="+ info ); } Listing 4.14 - An example of using a ResultSet object リスト 4.14 - ResultSet オブジェクトの利用例 In the above listing: 上記リストでは、以下が実行されています。 (1)スクロール可能 (かつ他のユーザーの更新を反映可能) であり更新可能なカーソルとなるよ うプロパティーをセットして、Statement オブジェクトを作成します。 (2) ResultSet オブジェクトを作成します。 (3) ResultSet 内をループします。 (4) id = 5003 であり、それが UNSHIPPED であるという条件に当てはまる場合、カーソルのあ る行の String (列 2) を “Shipped” の状態に更新します。もっと多くの列がある場合、他の 列も 更新メソッド (updateXXX) を使って更新することができます。 (5) 行を更新します。 (rs.insertRow() を使った場合、その場所に新しい行を挿入します。) (6) カーソルを、ResultSet オブジェクトの先頭、最初の行の直前に戻します。 4.3.4 SQL エラーと警告の処理 他の Java プログラムと同様に、JDBC では、例外処理は try-catch ブロックを使って行います。 DB2 アプリケーションは、SQL ステートメントの実行中に、SQL エラーが発生したときには SQLException を投げ、 SQL 警告が発生したときには SQLWarning を投げます。 第 4 章 – Java によるアプリケーション開発 143 4.3.4.1 SQLException SQLException オブジェクトは、データベースへアクセスしているときにエラーが発生した時に、 作成されて投げられます。SQLException オブジェクトは表 4.6 でリストされている情報を提供し ます。 SQLException の 情報 説明 情報を取得するメソッド Message エラー・コードを説明する文章 getMessage メソッド SQLState SQLState 文字列 getSQLState メソッド ErrorCode 例外を発生させたエラー内容を示す整数 値 getErrorCode メソッド 表 4.6 - SQLException の情報 上 記 の 情 報 と は 別 に 、 DB2 JCC ド ラ イ バ ー は 特 別 な イ ン タ ー フ ェ ー ス で あ る com.ibm.db2.jcc.DB2Diagnosable を提供しています。このインターフェースは、DB2 データ ベースにアクセス際に発生したエラーについて、より多くの情報を提供します。 複数の SQLException が投げられる場合、例外はチェーンされます。次の例外の情報は、現在の SQLException の getNextException メソッドを呼ぶことで取得できます。このメソッドは、現在 の SQLException がチェーンの中で最後のオブジェクトだった場合、null を返します。catch ブ ロックの中で while ループを使って、全ての SQLException オブジェクトを取得できます。リスト 4.15 は try-catch ブロック内で SQLException を処理する方法を示しています。 try { // code which can throw SQLException go here } catch (SQLException sqle) { System.out.println("Rollback the transaction and quit the program"); System.out.println(); try { con.rollback(); } catch (Exception e) {} System.exit(1); } リスト 4.15 - SQLException の処理 4.3.4.2 SQLWarning SQLWarning オブジェクトは、以下のクラスのメソッドを呼んでいる間にデータベースで警告が発 生したときに作成されます。 Connection 144 DB2 アプリケーション開発入門 Statement PreparedStatement CallableStatement ResultSet これらのインターフェースは全て、警告の情報を取得するための getWarning メソッドを持ってい ます。SQLWarning オブジェクトが作成されるときは、SQLException のように例外として投げら れることはないので、ご注意ください。警告が発生しているかどうかをチェックするためには、上記 のインターフェースの getWarning メソッドを呼ぶ必要があります。リスト 4.16 は警告を処理する 例です。 Statement stmt=con.createStatement(); stmt.executeUpdate("delete from product where pid='101'"); SQLWarning sqlwarn=stmt.getWarnings(); while(sqlwarn!=null) { System.out.println ("Warning description: " + sqlwarn.getMessage()); System.out.println ("SQLSTATE: " + sqlwarn.getSQLState()); System.out.println ("Error code: " + sqlwarn.getErrorCode()); sqlwarn=sqlwarn.getNextWarning(); } リスト 4.16 - SQLWarning の処理 4.3.5 接続の切断 JDBC プログラム開発のステップを完了するためにこのセクションを含んでいますが、Connection オブジェクトの close メソッドを使って接続を切断する方法は、既に前の例で示してあります。前の リスト 4.4 では、Statement オブジェクトや ResultSet オブジェクトのクローズ方法、対応する close メソッドの使い方も説明しています。 4.3.6 XML の利用方法 Java アプリケーション内での pureXML の利用方法は、非常に簡単です。いつも SQL ステートメ ントで利用しているのと同じ方法で、単純に SQL/XML や XQuery ステートメントを利用してくださ い。Java プログラム内では、XML は文字列として扱ってください。パフォーマンス面でのアドバン テージもあります。JDBC プログラムは XML 文書全てを文字列や CLOB (この形式で保管されて いる場合) として取得する必要はなく、実行時に DOM ツリーを作る必要もありません (DOM パー サーを使っている場合) 。SQL/XML や XQuery を使って DB2 内で必要な情報を取得してくださ い。 4.3.6.1 XML データの挿入 Java プログラムを使って XML 文書を挿入する時には、2 つの方法があります: 第 4 章 – Java によるアプリケーション開発 145 Java プログラムの中に XML をハード・コードして、文字列として挿入する。 XML 文書をファイルとして保存し、そのファイルを setBinaryStream メソッドを使って挿 入する。 たとえば、CLIENTS という表を以下のような DDL で作成したとしましょう: create table clients( id name status contactinfo int primary key not null, varchar(50), varchar(10), xml ) 最後の列の contactinfo は XML として定義されていることに注目してください。 図 4.7 はこの列 を文字列として扱う Java プログラムの例です。 図 4.7 - Java プログラム内でハード・コードされた XML 文書の挿入 上記の図の中で、xml 変数は文字列として定義されています。そして insertStmt.setString(4, xml) の行で、XML 列の contactInfo に対応する 4 番目のパラメーター・マーカーに xml 変数の値が セットされています。 146 DB2 アプリケーション開発入門 図 4.8 では、XML 文書は Java プログラム内にハード・コードされておらず、client1885.xml という ファイルに保存されています。そして、setBinaryStream メソッドを使って、このファイルをデータ ベースに挿入します。XML に関わるその他の処理は DB2 によって行われます。 図 4.8 - ファイルに保存された XML 文書の挿入 4.3.6.2 SQL/XML と XQuery を使った XML 文書の取得 第 2 章にある DB2 pureXML の説明は、この章にも当てはまります。図 4.9 は、Java プログラム 内で SQL/XML による照会を実行する例です。パラメーター・マーカーを利用しており、結果セット として返された 2 列目 (email) が、文字列として取得されています。照会からわかるように、email 列は contactInfo 列内に保存されている XML 文書の要素の一つです。 第 4 章 – Java によるアプリケーション開発 147 図 4.9 - Java プログラム内での SQL/XML の利用 図 4.10 は、Java プログラム内で XQuery を利用する例です。繰り返しますが、Java プログラム 内で SQL/XML や XQuery を利用するに当たって特別なことは何もありません。 図 4.10 - Java プログラム内での XQuery の利用 注: データベース・メタデータやバッチ更新、トランザクション、セーブポイント、ラージ・オブジェクトの 処理などのトピックも含む、より詳細な JDBC の説明が、IBM の Redbook である DB2 ExpressC: The Developer Handbook for XML, PHP, C/C++, Java, and .NET (SG24-7301-00) にあり ます。詳細はこの本のリソースの節をご覧ください。 148 DB2 アプリケーション開発入門 4.4 SQLJ プログラミング SQLJ プログラミングは、Java プログラム内に SQL を組み込むための標準手法です。全ての SQL ステートメントは コンテキスト を使って静的に実行されます。コンテキスト には SQL ステート メントがどこで実行されるのかを解釈するための情報が含まれます。コンテキスト にはいくつかの異 なるタイプが存在します。 接続コンテキスト。これは JDBC における Connection オブジェクトと等価です。接続コン テキストが指定されない場合、デフォルトの接続コンテキストが利用されます。 実行コンテキスト。ステートメントの実行前と実行後に、SQL ステートメントに関する情報を 取得するために必要です。 4.4.1 SQLJ の構文 SQLJ を利用する際、 Java プログラム内に組み込まれた SQL をプリコンパイラーが特定する事 ができるように、いくつか構文があります。構文にはいくつかの異なるタイプがありますが、以下のよ うに、全て “#sql” で始まり、中括弧を区切り文字として利用します。 #sql [connection-context] { sql statement } #sql [connection-context, execution context] { sql statement } #sql { sql statement } #sql [execution context] { sql statement } ホスト変数は、以下の例のようにコロンで定義されます。 #sql {SELECT EMPNO FROM EMP WHERE WORKDEPT = :dept}; 4.4.2 Connection コンテキスト SQLJ プログラム内で SQL を使うためには、最初にデータベースへの接続を確立する必要があり ます。接続コンテキストはそのために利用されます。以下のリスト 4.17 と リスト 4.18 で示すように、 接続コンテキストを利用する方法はいくつか存在します。 (1) #sql context ctx; // This should be outside the class (2) Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance(); (3) ctx ctx1 = new ctx(“jdbc:db2:sample”,false); (4) #sql [ctx1] { DELETE FROM dept }; リスト 4.17 - 接続コンテキストの利用 上記リストでは以下を実行しています。 (1) 以下の構文を使って、接続コンテキストのためにクラスを宣言します。 #sql context <context-class-name> (2) JDBC ドライバーをロードします。JDBC プログラムと同様です。 第 4 章 – Java によるアプリケーション開発 149 (3) context クラスのコンストラクターを呼びます。 (4) SQL ステートメント (DELETE) が接続コンテキスト “ctx1” のもとで実行されます。 リスト 4.18 にある別の例は同じような内容となっていますが、JDBC 接続オブジェクトを使って SQLJ と連携しています。 #sql context ctx; // This should be outside the class Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance(); (1) Connection con=DriverManager.getConnection(); (2) ctx ctx1 = new ctx(con); #sql [ctx1] { DELETE FROM dept }; リスト 4.18 - Connection オブジェクトから接続コンテキストを作る例: 上記リストでは以下を実行しています。 (1) Connection オブジェクトを利用します。 (2) context クラスのコンストラクターを呼びます。 加えて、接続のデフォルト・コンテキストを作成することも可能です。これはつまり、利用するコンテ キストがデフォルトとして指定されたものになるため、続けて SQL 操作を実行する際にコンテキスト を指定する必要がないことを意味します。構文は以下のようになります。 #sql { sql statement } リスト 4.19 がその例です。 Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance(); Connection con = DriverManager.getConnection(); (1) DefaultContext ctx1 = new DefaultContext(con); (2) DefaultContext.setDefaultContext(ctx1); (3) #sql { DELETE FROM dept }; リスト 4.19 - デフォルト・コンテキストを使った接続の例 上記リストでは以下を実行しています。 (1) DefaultContext を作成します。 (2) デフォルト・コンテキストが ctx1 になるよう設定します。 (3) 実行する SQL を記述します。このケースでは DELETE ステートメントです。構文の中にコ ンテキスト名を含める必要がないことに注目してください。デフォルト・コンテキストである ctx1 が利用されます。 以下のリスト 4.20 は、デフォルト・コンテキストを使った SQLJ プログラムの全文の例です。 import java.sql.*; (1) import sqlj.runtime.*; // SQLJ runtime support (2) import sqlj.runtime.ref.*; // SQLJ runtime support 150 DB2 アプリケーション開発入門 class myprg3 { public static void main(String argv[]) { try { Connection con = null; Class.forName("com.ibm.db2.jcc.DB2Driver"); String url = "jdbc:db2://127.0.0.1:50000/SAMPLE"; if (argv.length == 2) { String userID = argv[0]; String passwd = argv[1]; con = DriverManager.getConnection(url,userID,passwd); } else { throw new Exception ("\n Usage: java myprg3 userID password\n"); } (3) DefaultContext ctx = new DefaultContext(con); (4) DefaultContext.setDefaultContext(ctx); (5) if( ctx != null ) (6) { ctx.close();} } catch (Exception e) { } }} リスト 4.20 - SQLJ プログラムの全文 上記リストでは以下を実行しています。 1 と 2: SQLJ ランタイムのサポートのため、これらのパッケージをインポートする必要があります。 3. デフォルト・コンテキストを作成します。 4. 利用するデフォルト・コンテキストを設定します。 5. コンテキストがクローズされていない場合、 6. コンテキストをクローズし、切断します。 4.4.3 実行コンテキスト 実行コンテキストは、実行中の SQL ステートメントをモニターし制御します。JDBC の Statement インターフェースと等価であり、接続コンテキスト・オブジェクト内で作成されます。 実行ステートメントを作成するためには、接続コンテキストの getExecutionContext メソッドを使 います。ExecutionContext のメソッドには、SQL ステートメントが実行される前に使われるものと、 実行後のみに使われるものがあります。 リスト 4.21 は実行コンテキストの利用例です。 #sql context ctx; // this should be outside the class String url = "jdbc:db2:sample"; Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance(); 第 4 章 – Java によるアプリケーション開発 151 Connection con=DriverManager.getConnection(url); ctx ctx1=new ctx(con); (1) ExecutionContext exectx1 = ctx1.getExecutionContext(); (2) #sql[ctx1,exectx1] = { DELETE FROM purchaseorder WHERE status='UnShipped'} (3) int i = exectx1.getUpdateCount(); リスト 4.21 - 実行コンテキストの利用例 上記リストでは以下を実行しています。 (1) 接続コンテキスト・オブジェクトの getExecutionContext メソッドを使って、実行コンテキ ストを作成します。 (2) 接続コンテキスト ctx1 と、実行コンテキスト exectx1 に関連づけて実行する SQL を記述 します。 (3) 実行コンテキスト・オブジェクトの getUpdateCount メソッドを実行し、削除もしくは更新さ れた行の数を取得します。 4.4.4 イテレーター イテレーターは JDBC の結果セットと同様のものです。イテレーターには 2 つのタイプがあります。 名前指定イテレーター: 結果セット内の列の名前で行を特定します。名前指定イテレータ ーを定義する時には、列の名前とデータ・タイプを指定します。 位置指定イテレーター: 結果セット内の位置で行を特定します。位置指定イテレーターを 定義する時には、列のデータ・タイプのみを指定します。 リスト 4.22 は名前指定イテレーターの例です。 (1) #sql iterator namediterator (int poid, String status) (2) namediterator iterator1; (3) #sql [ctx1] iterator1 = { select poid,status from purchaseorder }; (4) while(iterator1.next()) { (5) System.out.println("poid: " + iterator1.poid() + "Status: "+ iterator1.status()); } (6) iterator1.close(); リスト 4.22 - 名前指定イテレーターの例 上記リストでは以下を実行しています。 (1) 名前指定イテレーターを 2 つ の列で宣言します。列名の poid と status を明示的に指 定することに注目してください。この指定方法によって名前指定イテレーターであることが わかります。 (2) 名前指定イテレーター iterator1 を宣言します。 152 DB2 アプリケーション開発入門 (3) 接続コンテキスト ctx1 の中で、iterator1 を “select poid, status from purchaseorder” として 定義します。 (4) イテレーターをループします。 (5) 取得された各行の poid と status を出力します。”iterator1.poid()” と “iterator1.status()” と いう構文に注目してください。 (6) iterator1 をクローズします。 リスト 4.23 は位置指定イテレーターの例です。 (1) #sql iterator positionedIterator (int, String); (2) String status = null; (3) int poid = 0; (4) positionedIterator iterator1; (5) #sql [ctx1] iterator1={ select poid, status from purchaseorder }; (6) #sql { fetch :iterator1 into :poid, :status }; (7) while(!iterator1.endFetch()) { (8) System.out.println("poid: " + poid + "Status: "+ status); (9) #sql { fetch :iterator1 into :poid, :status }; } リスト 4.23 - 位置指定イテレーターの例 上記リストでは以下を実行しています。 (1) 位置指定イテレーターを 2 つの列で定義します。列名はなく、データ・タイプのみであるこ とに注目してください。この指定方法によって位置指定イテレーターであることがわかりま す。 (2) status 変数を宣言します。これはイテレーターから値を受け取るためのホスト変数と同様 のものです。 (3) 2 と同様に poid 変数を宣言します。 (4) 位置指定イテレーター iterator1 を作成します。 (5) 接続コンテキスト ctx1 の中で、iterator1 を “select poid, status from purchaseorder” として 定義します。 (6) ループを開始する前に、最初のレコードをホスト変数 poid と status にフェッチします。こ れは、(7) で next() を使わずに endFetch() を使っていて、while ループの終了条件が next() と endFetch() で異なるためです。 (7) イテレーターをループします。 (8) 取得された各行の poid と status を出力します。 (9) イテレーターの次の行をフェッチします。 名前指定イテレーターと位置指定イテレーターは更新可能やスクロール可能として定義する事が できます。デフォルトでは、SQLJ のイテレーターは読み取り専用で順方向のみに移動できます。 第 4 章 – Java によるアプリケーション開発 153 スクロール可能イテレーターを定義するためには、イテレーターを定義する際に sqlj.runtime.Scrollable を実装する必要があります。 更新可能イテレーターを定義するためには、イテレーターを定義する際に sqlj.runtime.ForUpdate を実装する必要があります。更新可能イテレーターを定義する時には、 更新したい列も指定する必要があります。 これは JDBC と同様です。リスト 4.24 は更新可能イテレーターの例です。 (1) #sql public iterator namediterator implements sqlj.runtime.ForUpdate with (updateColumns="STATUS") (int poid, String status); (2) namediterator iterator1; (3) #sql [ctx1] iterator1={ select poid,status from purchaseorder }; (4) while(iterator1.next()) { (5) System.out.println("before update poid: " + iterator1.poid() + "Status: "+ iterator1.status()); (6) if(iterator1.status().toUpperCase().compareTo("UNSHIPPED")==0){ #sql [ctx1] {update purchaseorder set status= 'shipped' where current of :iterator1 }; } (7) #sql [ctx1] {commit}; リスト 4.24 - 更新可能イテレーターの例 上記リストでは以下を実行しています。 (1) 名前指定イテレーターを宣言します。sqlj.runtime.ForUpdate を実装しているため更新 可 能 イ テ レ ー タ ー と し て 定 義 さ れ て い ま す 。 更 新 対 象 の 列 を with (updateColumns="STATUS") として示していることにも注目してください。 (2) 名前指定イテレーター iterator1 を宣言します。 (3) iterator1 を select poid,status from purchaseorder” の結果として定義します。 (4) イテレーターをループします。 (5) イテレーターの各行を出力します。 (6) status 列が “UNSHIPPED” であるかを判定します。合致した場合、値を ‘shipped’ に変 更します。 (7) 変更をコミットします。 4.4.5 JDBC と SQLJ の同時利用 JDBC と SQLJ は一つのアプリケーション内で同時に利用する事が可能です。例えば、JDBC の 接続オブジェクトは ConnectionContext オブジェクトから getConnection メソッドを使って取得 でき、またその逆も可能です。 SQLJ のイテレーターと JDBC の ResultSet は以下のように相互に取得可能です。 ResultSet からイテレーター: #sql iterator = {CAST :result-set } 154 DB2 アプリケーション開発入門 イテレーターから ResultSet: イテレーターの getResultSet メソッドの利用 リスト 4.25 は一つのプログラム内での JDBC と SQLJ の同時利用の例です。 #sql public iterator positionIterator (int, String); Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance(); Connection con=DriverManager.getConnection(url); con.setAutoCommit(false); (1) ctx ctx1=new ctx(con); positionIterator iterator; Statement stmt = con.createStatement(); ResultSet rs=stmt.executeQuery("select poid, status from purchaseorder"); (2) #sql [ctx1] iterator={cast :rs}; #sql {fetch :iterator into :poid, :status}; while(!iterator.endFetch()) { System.out.println("id: "+poid+" status: "+status); #sql {fetch :iterator into :poid, :status}; } iterator.close(); リスト 4.25 - 一つのプログラム内での JDBC と SQLJ の同時利用 上記リストでは以下を実行しています。 (1) 接続オブジェクトを使って SQLJ 接続コンテキストを作成します。 (2) この方法で、JDBC の ResultSet から SQLJ のイテレーターを取得します。 4.4.6 SQLJ プログラムの準備 SQLJ プログラムの準備は、プログラムのプリコンパイルとバインドが必要となる組み込み SQL で 必要なプロセスと似ています。SQLJ の場合、SQLJ プログラムは変換とカスタマイズが必要です。 図 4.11 は プログラム myprg3.sqlj を準備するためのプロセスを示しています。 第 4 章 – Java によるアプリケーション開発 155 図 4.11 – SQLJ プログラムを準備するためのステップ 図の中で、SQLJ プログラム myprg3.sqlj は、sqlj コマンドによって SQLJ 変換プログラムへ渡さ れます。SQLJ 変換プログラム は ”#sql” で始まる行を探して検査し、その行を SQLJ ランタイム・ クラスを含むように生成されたコードへと置き換え、.java 拡張子のファイルを作成します。その後、 このファイルを Java コンパイラー (javac) を使ってコンパイルし、.class ファイルを作成します。 SQLJ 変換プログラムは、図の上部で示されているように、接続コンテキスト・クラスごとに、SQLJ 実行可能節内で使われるシリアライズド・プロファイルも作成します。この例では myprg3_SJProfile0.ser と myprg3_SJProfile1.ser の 2 つのシリアライズド・プロファイルがありま す。これらのファイルは組み込み SQL に関する情報を保持しています。javac が実行された後、 これらのファイルから myprg3_SJProfileKeys.class ファイル (図には存在しない) が作成されます。 db2sqljcustomize コマンドで DB2 カスタマイザーを呼び出すことで、パッケージ (コンパイルさ れた SQL) がデータベース内に作成されます。 プログラムを実行したいときには、単純に java myprg3 コマンドを使って実行してください。 myprg3.class ファイルとデータベース内の対応するパッケージが利用されます。 注: myprg3.sqlj プログラムは、この本に付属している zip ファイルの Exercise_Files_DB2_Application_Development.zip に含まれています。このファイルで確認、 テスト、および準備ができます。 以下が、実際にこれら全てのコマンドの実行結果とその出力の例です。以下のようなステップで実 行します: (1) SQLJ 変換プログラム (sqlj コマンド) を実行します。 156 DB2 アプリケーション開発入門 D:\>sqlj myprg3.sqlj 以下のファイルが作成されます: myprg3.java, myprg3.class, myprg3_SJProfile0.ser, myprg3_SJProfileKeys.class (2) DB2 カスタマイザー (db2sqljcustomize コマンド) を各 .ser ファイルごとに実行します。DB2 カスタマイザーはいくつかのパラメーターを受け取ります。渡すパラメーターは、基本的には Java プログラムが接続する必要があるデータベースの情報であり、そこにパッケージが保存さ れることになります。例えば: D:\>db2sqljcustomize -url jdbc:db2://localhost:50000/sample -user rfchong -password mypasswd myprg3_SJProfile0.ser このうち: -url jdbc:db2://localhost:50000/sample は接続する必要のあるデータベースの URL です -user rfchong はデータベースに接続するユーザー ID です。 -password mypasswd はデータベースに接続するためのパスワードです。 myprg3_SJProfile0.ser はデータベースのパッケージを作成するためのカスタマイズド・プロ ファイルのファイル名です。 出力は以下のリスト 4.26 のようになります。 [jcc][sqlj] [jcc][sqlj] Begin Customization [jcc][sqlj] Loading profile: myprg3_SJProfile0 [jcc][sqlj] Customization complete for profile myprg3_SJProfile0.ser [jcc][sqlj] Begin Bind [jcc][sqlj] Loading profile: myprg3_SJProfile0 [jcc][sqlj] Driver defaults(user may override): BLOCKING ALL VALIDATE BIND STATICREADONLY YES [jcc][sqlj] Fixed driver options: DATETIME ISO DYNAMICRULES BIND [jcc][sqlj] Binding package MYPRG301 at isolation level UR [jcc][sqlj] Binding package MYPRG302 at isolation level CS [jcc][sqlj] Binding package MYPRG303 at isolation level RS [jcc][sqlj] Binding package MYPRG304 at isolation level RR [jcc][sqlj] Bind complete for myprg3_SJProfile0 リスト 4.26 - DB2 カスタマイザー実行時の出力 第 4 章 – Java によるアプリケーション開発 157 出力ファイルは作成されませんが、組み込み SQL から作成されたパッケージとアクセス・プランが データベースに保存されます。 (3) プログラムを実行します。事前に作成されたパッケージが実行時に利用されます。 D:\>java myprg3 <userid> <password> Successful connection to the database! Successful retrieval of record. Column 'IBMREQD' has a value of 'Y' Successful Disconnection from database End of Program 以下の図 4.12 はプログラム myprg3.sqlj を準備する際の全ての出力です。 158 DB2 アプリケーション開発入門 図 4.12 - SQLJ プログラム myprg3.sqlj の準備 4.5 pureQuery 現時点で JDBC と SQLJ に関する基本知識は身についているはずです。既にお気づきかもしれ ませんが、旧来の JDBC と SQLJ のプログラミングでは、少し冗長なプログラミングが必要となりま す。これが、Hibernate のような オブジェクト関係マッピング (ORM) フレームワークが人気となった 理由の一つです。このフレームワークは、オブジェクト指向のコードとリレーショナル・データベー ス・モデルの間のマッピングを行うデータ・アクセス抽象化レイヤーを提供します。しかし、ORM フ レームワークはユーザーに見えない形で SQL を生成することが多く、生成された SQL は最適な ものにはならないかもしれません。さらに、データベースに送られる SQL を開発者で制御すること ができないため、パフォーマンス問題の調査やチューニングがより複雑になります。 これらの課題に対しての答えとして、IBM は pureQuery を開発しました。pureQuery は、JDBC の上に存在する API の薄いレイヤーであると考えてください。ORM フレームワークと同様にリレー ショナル・モデルとオブジェクト指向のコードのマッピングを行いますが、自分で記述した SQL を 利用できる柔軟さも提供します。そのため、pureQuery のプログラミング・モデルとツールは、Java によるデータ・アクセスの手助けとなり、JDBC のようなバッチ更新などを使うベスト・プラクティスの アプローチを用いてコードを生成することでパフォーマンスを向上させ、さらに問題判別の手助け となります。 APIに加えて、pureQuery は以下のようなものも提供します。 最適でセキュアなデータ・アクセスを提供するランタイム 開発の生産性向上のための、Eclipse ベースの統合されたデータベース開発環境 開発者やデータベース管理者に、 Java データベース・アプリケーションのパフォーマンス について事前には判明していなかった見解を与えるための、モニター・サービス pureQuery では、コードの変更なしに静的 SQL を生成することもできます。これによって、苦労な く静的 SQL の利点を得る事ができます。 pureQuery のためのツールは Optim Development Studio という製品に含まれています。API とランタイムは Optim pureQuery Rutime という製品で利用可能で、開発者のマシン上での開発 目的であれば、無償で Optim Development Studio にパッケージされています。モニター・サー ビ ス は Optim Development Studio に よ っ て 提 供 さ れ 、 さ ら に 多 く の 機 能 が IBM DB2 Performance Expert と Extended Insight Feature によって提供されます。 IBM Optim 製品群は、ライフ・サイクルを通して企業データをデザイン、開発、デプロイ、操作、最 適化、そして管理するための統合されたモジュール式の環境を提供します。これは Optim Integrated Data Management として知られています。 注: pureQuery と Optim Integrated Data Management についてのより多くの情報は、無償の e ブッ クである Getting Started with pureQuery と Getting Started with IBM Data Studio for DB2 に それぞれ載っています。どちらの e ブックもこの本のシリーズの一部です。 第 4 章 – Java によるアプリケーション開発 159 4.6 演習 この演習では、小さい JDBC と SQLJ プログラムを書く練習をします。 手順 1. リスト 4.12 で一つの結果セットを取得するために CallableStatement オブジェクトを使う例を説 明しました。以下のような仕様をもつ JDBC プログラムを作成してください。 - プログラム名: mylab4.java - プログラムは以下のような構文で実行される。 java mylab4 <userid> <password> <bonus> - SAMPLE データベースにタイプ 4 ドライバーを使って接続する。 - 2 つの結果セットを返すストアード・プロシージャー “high_bonus” を呼ぶ。 - まず以下のようなストアード・プロシージャー high_bonus を作成する。 CREATE PROCEDURE HIGH_BONUS (IN p_bonus INT) DYNAMIC RESULT SETS 2 ------------------------------------------------------------------------- This procedure lists the first name, last name, bonus, and -- education level (edlevel) of the employees with a bonus amount -- larger than the amount specified by the parameter p_bonus. -- This information is in the EMPLOYEE table. -- The procedure also returns another result set with the names -- of all departments from the DEPARTMENT table. -----------------------------------------------------------------------P1: BEGIN -- Declare cursor1 DECLARE cursor1 CURSOR WITH RETURN FOR SELECT firstnme, lastname, bonus, edlevel FROM employee WHERE bonus > p_bonus; -- Declare cursor2 DECLARE cursor2 CURSOR WITH RETURN FOR SELECT deptname FROM department; -- Cursor left open for client application OPEN cursor1; OPEN cursor2; END P1 160 DB2 アプリケーション開発入門 プログラム mylab4.java (回答) はこの本に付属している Exercise_Files_DB2_Application_Development.zip ファイルに含まれています。 2. この本に付属している Exercise_Files_DB2_Application_Development.zip ファイル内の connectionContext.sqlj ファイルを確認してください。この SQLJ プログラムを準備して、実行 してください。 4.7 まとめ この章では、DB2 を使った Java アプリケーションの開発の基本についてご説明しました。動的 SQL を使ってデータベースにアクセスする標準的な API である JDBC について最初にご説明し ました。そして、DB2 のデータベースへの接続方法と異なる種類の JDBC ステートメントの実行方 法を示しました。続いて、SQLJ をご説明しました。JDBC ほど知られてはいないですが、SQLJ プ ログラミングは Java プログラムに組み込まれた静的 SQL を利用するための、簡潔でパフォーマン スのよいプログラミング方法です。最後に、IBM の pureQuery について簡単にご紹介しました。 pureQuery は、JDBC プログラミングの冗長さと ORM フレームワークの柔軟さの欠如に対する IBM の答えです。 4.8 確認問題 1. JDBC と SQLJ の違いは何ですか? 2. DB2 9.7 ではどの JDBC のタイプがサポートされていますか? 3. db2jcc.jar と db2jcc4.jar の違いは何ですか? 4. イテレーターとはどのようなものですか? 5. デフォルト・コンテキストとはどのようなものですか? 6. 以下の文章のうち誤りのある文章はどれですか? A. db2jcc.jar は JDBC タイプ 2 ドライバーを含んでいる。 B. db2jcc4.jar は JDBC タイプ 2 ドライバーを含んでいる。 C. db2jcc.jar は JDBC タイプ 4 ドライバーを含んでいる。 D. db2jcc4.jar は JDBC タイプ 4 ドライバーを含んでいる。 E. 上記のいずれでもない。 7. 以下の文章のうち正しい文章はどれですか? A. pureQuery では、開発者はコードの変更をせず簡単に SQL を動的に実行したり静的 に実行したりすることができる。 B. pureQuery は ORM として利用することができる。 C. pureQuery はいくつかの Optim 製品に含まれている。 D. 上記の全て 第 4 章 – Java によるアプリケーション開発 161 E. 上記のいずれでもない 8. 以下の文章のうち正しい文章はどれですか? A. JDBC と SQLJ は連携させることができない。 B. JDBC と pureQuery は連携させることができない。 C. SQLJ と pureQuery は連携させることができない。 D. JDBC と SQLJ と pureQuery は連携させることができない。 E. 上記のいずれでもない。 9. 以下のオブジェクトのうちステートメントのオブジェクトとして正しくないものはどれかです か? A. Statement B. PreparedStatement C. CallableStatement D. ResultSetStatement E. 上記のいずれでもない 10. SQLJ の考え方には存在しないものはどれですか? A. 実行可能コンテキスト B. 接続コンテキスト C. デフォルト・コンテキスト D. 名前指定イテレーター E. 位置指定イテレーター 5 第 5 章 C/C++でのアプリケーション開発 この章では DB2 における C および C++を使用するアプリケーション開発のさまざまな側面を、開 発環境のセットアップからアプリケーションの構築と実行までを通して説明します。組み込み SQL は第 1 章 DB2 アプリケーション開発の前半でも説明していますが、ここでは C および C++のプロ グラムで組み込み SQL をどのようにプログラミングするのかをより詳しくみていきます。この章では ODBC や CLI アプリケーションをどのように開発するかについても述べます。この章では以下の内 容を説明します: 組み込み SQL を使用する C および C++アプリケーションのプログラミング 組み込み SQL を使用する C および C++アプリケーションの構築 CLI および ODBC を使用する C および C++アプリケーションのプログラミング CLI および ODBC を使用する C および C++アプリケーションの構築 5.1 C/C++ DB2 アプリケーション: 全体像 データベース・アプリケーションに関して述べるとき、まず思い浮かぶのは SQL でしょう。SQL はリ レーショナル・データベースにおいて、データ定義言語(DDL)やデータ制御言語(DCL)、データ操 作言語(DML)を実行するために使用される言語です。SQL は汎用的なプログラミング言語ではあ りません。SQL はデータベース・マネージャーによって実行される非手続き型言語であるため、ユ ーザーの定義する操作を実行することはできません。そのような理由から、データベース・アプリケ ーションの多くが、SQL の機能と C や C++のような高級プログラミング言語を組み合わせて開発さ れています。ホスト言語ともよばれる高水準言語によるアプリケーション開発や、アプリケーション内 に SQL ステートメントを組み込むことは、組み込み SQL プログラミングとして知られています。図 5.1 はこの概念を示したものです。組み込み SQL アプリケーションは多くの場合 C や C++を用い て開発されています。 図 5.1 – 組み込み C/C++ SQL アプリケーション 164 DB2 アプリケーション開発入門 C/C++アプリケーションは、クライアント/サーバー・アーキテクチャーのクライアントとして動作し、 DB2 がサーバーとして稼動します。クライアントはサーバーにリクエストを送信し、サーバーは操作 を実行します。C/C++アプリケーションは、組み込み SQL アプリケーションであることもありますし、 CLI/ODBC アプリケーションであることもあります。図 5.2 は、C/C++アプリケーションが DB2 サー バーと対話するクライアント/サーバー・アーキテクチャーを示しています。 図 5.2 – DB2 サーバーにアクセスする C/C++アプリケーション 図 5.2 では、C/C++アプリケーションがどのように構築され、DB2 データベースにアクセスできるの かを示しています。SQL ステートメントを含む組み込み SQL アプリケーションは DB2 プリコンパイ ラーによってプリコンパイルされてなければいけません。このプリプロセスを進めるために、アプリケ ーション内に組み込まれたそれぞれの SQL ステートメントは、EXEC SQL キーワードとともに始ま り、セミコロン(;)で終わる必要があります。 一方で、CLI または ODBC は組み込み動的 SQL の代替方法ですが、組み込み SQL とは違っ て、これはホスト変数またはプリコンパイラーを必要としません。アプリケーションは、個別の ODBC ドライバーを提供する異なるベンダーによるさまざまなデータベースに対して実行することができま す。これらのデータベースに対して個別にコンパイルをする必要はありません。CLI/ODBC アプリ ケーションの処理は、CLI/ODBC ドライバーによって行われます。アプリケーションは、データベー スへの接続や、SQL の実行、データやステータス情報の取得のために実行時にプロシージャーコ ールを使用します。 上記のそれぞれの方法の詳細については以降の章で説明します。 5.2 環境の設定 組み込み SQL C/C++ アプリケーションまたは CLI/ODBC アプリケーションの構築を始める前に、 サポートされている C/C++コンパイラーをインストールする必要があります。組み込み SQL C/C++ プログラムのためにはプリコンパイラーも必要ですが、これは DB2 に同梱されています。 第 5 章 - C/C++でのアプリケーション開発 165 5.2.1 サポートされるコンパイラー 表 5.1 は 32 ビットおよび 64 ビットプラットフォーム上の DB2 データベース・アプリケーションに対 するサポートされている C/C++コンパイラーの一覧です。 オペレーティング・シ ステム サポートされるコンパイラー AIX® IBM XL C/C++ Enterprise Edition Version 7.0 for AIX IBM XL C/C++ Enterprise Edition Version 8.0 for AIX IBM XL C/C++ Enterprise Edition Version 9.0 for AIX Linux GNU/Linux gcc versions 3.3 および 3.4 Intel C Compiler Version 9.1 Intel C Compiler Version 10.1 Windows® Intel Proton Compiler (Windows 32 ビット・アプリケーション版) バージ ョン 9.0.021 以降 Microsoft® Visual C++ .NET 以降 表 5.1 – サポートされる C/C++ コンパイラー 注: この表は完全ではありません。サポートされる C/C++コンパイラーのバージョンに関する詳細な 情 報 お よ び 最 新 の 情 報 に つ い て は 、 DB2 9.7 イ ン フ ォ メ ー シ ョ ン ・ セ ン タ ー (http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.gs.doc/ doc/r0023434.html) と DB2 ア プ リ ケ ー シ ョ ン 開 発 Web サ イ ト (http://www.ibm.com/software/data/db2/udb/ad/)を参照して下さい。 この本では Microsoft Visual C++ コンパイラー (Windows) と GNU/Linux gcc コンパイラー (Linux)を使用します。Microsoft Visual C++ コンパイラーは Microsoft Visual Studio に同梱され て い る ソ フ ト ウ ェ ア で す 。 Visual Studio の エ ク ス プ レ ス ・ バ ー ジ ョ ン は 、 http://www.microsoft.com/express/Downloads/ からダウンロードできます。 GNU Linux gcc コンパイラーは GNU オペレーティング・システムに無償で同梱されていますが、 http://gcc.gnu.org/ からダウンロードすることもできます。 5.2.2 C/C++環境の設定 C/C++環境をセットアップするために、下記の手順が必要になります。 1. サポートされている C/C++コンパイラーがインストールされていること 166 DB2 アプリケーション開発入門 DB2 Express-C のサポートされるプラットフォーム上に、サポートされる C/C++コンパイラ ーがインストールされていることを確認して下さい。 Linux 上では、C/C++コンパイラーが正しくインストールされているかどうかを確認する為 に、シェル上から下記のコマンドを実行してください: which gcc コンパイラーがインストールされている場合、 画面上に/usr/bin/gcc と表示されるはずで す。 Windows で Microsoft Visual C++ コンパイラーを使用している場合、cl コマンドを実行 して下さい。図 5.3 はこのコマンドを実行した結果を示しています。 図 5.3 – cl コマンドの出力 Intel コンパイラーを使用している場合、cl または ecl コマンドを実行して下さい。図 5.4 はこのコマンドの実行結果を示しています。 図 5.4 –icl コマンドの出力 2. インストールされた DB2 が必要なライブラリーおよびヘッダー・ファイルを持っていること DB2 をインストールした後、C/C++プログラムを開発するために必要な、静的および共有 ライブラリー、ヘッダー・ファイル群が存在しているかを確認して下さい。 Linux では、これは DB2 インストール・ディレクトリーへ移動し、lib32 と lib64 ディレクトリ ーを確認することで分かります。たとえば、DB2 インストール・ディレクトリーが$HOME の 場 合 、 32 ビ ッ ト ラ イ ブ ラ リ ー は $HOME/sqllib/lib32 に 、 64 ビ ッ ト ラ イ ブ ラ リ ー は $HOME/sqllib/lib64 に配置されます。 第 5 章 - C/C++でのアプリケーション開発 167 Windows では、静的ライブラリーは<DB2 install directory>\lib に配置されます。図 5.5 は静的ライブラリーの場所を示しています。この例では DB2 インストール・ディレクトリー は C:\Program Files\SQLLIB となっています。 図 5.5 – Windows 版 DB2 でのライブラリーとヘッダー・ファイルの場所 3. Windows 環境の確認 Windows 開発機では、環境変数 INCLUDE に%DB2PATH%\include が Microsoft プラット フォームのいかなる SDK のインクルード・ディレクトリーよりも前に、含まれるようにして下さい。 コマンド・プロンプトで以下のコマンドを実行することで INCLUDE 変数を変更して下さい (これは現行のウィンドウでのみ有効です): set INCLUDE=%DB2PATH%\include;%INCLUDE% この変更を恒久的にしたい場合、マイコンピュータを右クリックし、プロパティー→環境変数 で Windows 環境変数を表示し、%DB2PATH%\include を INCLUDE 変数に追加して 下さい。 Visual Studio を 使 用 す る 開 発 の た め に は 、 INCLUDE 環 境 変 数 の 先 頭 に DB2PATH%\INCLUDE を含んでいなければいけません。このために以下の手順でコンパ イラーのための環境のアップデートが必要です: 1. Visual Studio のコマンド・プロンプトのショートカットをオープンします。(プログラ ムファイル→Microsoft Visual Studio .NET → Visual Studio .NET ツール→ Visual Studio .NET コマンド・プロンプト ) 168 DB2 アプリケーション開発入門 2. Visual Studio コマンド・プロンプトのウィンドウで、db2cmd.exe を実行し、DB2 コマンド・ウィンドウを開きます。 3. DB2 コマンド・ウィンドウで、以下のように INCLUDE パスを設定します: set INCLUDE=%DB2PATH%\INCLUDE;%INCLUDE% 図 5.7 は上記の手順を示しています。 図 5.7 – Windows 環境の設定 これで DB2 環境と C/C++環境が正しく設定された DB2 CLP ウィンドウ上でアプリケーション の構築ができます。 5.3 組み込み SQL の C/C++ アプリケーション の開発 この節では組み込み SQL の C/C++アプリケーションを開発するために必要な手順について述べ ます。 第 5 章 - C/C++でのアプリケーション開発 169 5.3.1 ソース・ファイルの拡張子 組み込み SQL の C/C++プログラムのソース・ファイルは DB2 プリコンパイラーが認識できる拡張 子にする必要があります。表 5.2 は、プリコンパイラーに必要なソース・ファイルの拡張子の一覧で す。 プラットフォーム C ソース・ファイル C++ ソース・ファイル Linux .sqc .sqC Windows .sqc .sqx 表 5.2 – サポートされるソース・ファイルの拡張子 5.3.2 C/C++における SQL データ・タイプ アプリケーションとデータベース間の通信のために、ホスト変数の C/C++データ・タイプと SQL デ ータ・タイプの正しいデータ・マッピングを使用することは非常に重要です。プリコンパイラーはホス ト変数の宣言をみつけると、それを適切な SQL データ・タイプとして定義します。表 5.3 は C/C++ におけるサポートされる SQL データ・タイプをいくつか示しています。 SQL 列タイプ C/C++ データ・タイプ SQL 列タイプ記述 SMALLINT Short 16 ビットの符号付き整数 INTEGER sqlint32 32 ビットの符号付き整数 DOUBLE Double 倍精度浮動小数点 CHAR(n) char[n+1] (n はデータを収容 するのに十分な大きさ) 固定長、NULL 終了文字ストリ ング 1<=n<=254 VARCHAR(n) char[n+1] (n はデータを収容 するのに十分な大きさ) NULL 終了可変長ストリング 1<=n<=32 672 DATE char[11] NULL 終了文字形式 TIME char[9] NULL 終了文字形式 Table 5.3 – C/C++でのサポートされる SQL データ・タイプ 注: この表は完全ではありません。完全なマッピングのリストは以下のページを参照して下さい。 http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.apdv.em bed.doc/doc/r0006090.html 170 DB2 アプリケーション開発入門 5.3.3 組み込み SQL C/C++アプリケーションの開発手順 組み込み SQL の C/C++アプリケーションの開発は以下のような手順を含みます: 1. 必要なヘッダー・ファイルをインクルードする 2. ホスト変数を宣言する 3. データベースに接続する 4. SQL ステートメントを実行する 5. SQL エラーを処理する 6. トランザクションをコミットする 7. データベースから切断する それぞれの手順を一つずつ見ていきましょう。リスト 5.1 は、C で記述された組み込み SQL アプリ ケーションに必要な構造を持った基本的なテンプレートです。 (1) /* Include required header files (2) /* Declaration of host variables */ EXEC SQL BEGIN DECLARE SECTION; ....... ....... EXEC SQL END DECLARE SECTION; /* Declaration of SQLCA structure */ EXEC SQL DECLARE SQLCA; /* Declaration of main function */ void main() { /* Connect to the database */ (3) EXEC SQL CONNECT TO <database name> ; /* Error handling to check connection is successful*/ if (SQLCODE < 0) { printf ("\n Error while connecting to database"); printf ("\n Returned SQLCODE = "); exit; } else { printf ("\n Connect to database successfully"); 第 5 章 - C/C++でのアプリケーション開発 171 } /* End of error handling */ (4) /* Execute SQL statements EXEC SQL SELECT <col1>, <col2> INTO :var1 :var2 FROM <table name> WHERE <condition> ; /* Error handling to check SQL statement executed successfully */ (5) if (SQLCODE < 0) { printf ("\n Error while executing SQL statement"); printf ("\n Returned SQLCODE = "); exit; } (6) /* Commit the transaction */ EXEC SQL COMMIT; /* Error handling to check SQL statement executed successfully */ if (SQLCODE < 0) { printf ("\n Error while Commiting data"); printf ("\n Returned SQLCODE = "); exit; } (7) /* Disconnect from the database */ EXEC SQL DISCONNECT FROM <database name>; /* Error handling to check whether disconnection is successful */ if (SQLCODE < 0) { printf ("\n Error while disconnecting from database"); printf ("\n Returned SQLCODE = "); exit; } else { printf ("\n Disconnect from database successfully"); } } リスト 5.1 – 組み込み SQL C プログラムのテンプレート リスト 5.1 の中の各項目に関しては、以下の節で詳しく述べます。 172 DB2 アプリケーション開発入門 注: 上 記 の テ ン プ レ ー ト は template.sqc の フ ァ イ ル 内 に あ り 、 こ れ は こ の 本 を 含 む Exercise_Files_DB2_Application_Development.zip の中にあります。 5.3.4 組み込み SQL の C/C++ アプリケーションの例 前節で述べた各手順を示すために、あるサンプル・アプリケーションを使用します。このアプリケー ションは、従業員の情報を表に追加、更新、読み込み、削除ができる従業員管理システムです。図 5.8 はアプリケーションが何をするのかの全体像を示しています。 図 5.8 – 組み込み SQL C/C++ アプリケーションの関数の例 表 5.4 は、図 5.8 に書かれている関数の説明です。 Function Operation AddEmployeeInfo( ) 表に新しい従業員情報を挿入します UpdateEmployeeInfo( ) 表の従業員の給料を更新します FetchEmployeeInfo( ) 表から従業員情報を選択します DeleteEmployeeInfo( ) 表から従業員情報を削除します 表 5.4 – 様々な操作を行う関数 注: この節の中の全てのコード・スニペットは、embeddedC.sqc から引用したものです。このファイルは この本を含む Exercise_Files_DB2_Application_Development.zip の中に含まれています。 5.3.4.1 必要なヘッダー・ファイルのインクルード 組み込みアプリケーションの最初のステップは、必要なヘッダー・ファイルをインクルードすることで す。sqlca.h は SQL に関連するおそらく最も重要なヘッダー・ファイルであり、その他はその C ア プリケーションが何をするのかに依存します。 第 5 章 - C/C++でのアプリケーション開発 173 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sqlca.h> リスト 5.2 – 必要なヘッダー・ファイルのインクルード 5.3.4.2 ホスト変数の宣言 第一章 DB2 アプリケーション開発の概要で述べたように、組み込み SQL アプリケーションは、ホ スト変数を用いて C/C++ホスト言語と通信をします。この 2 番目のステップでは、プログラムの先頭 の DECLARE 節において、ホスト変数を宣言しなければなりません。リスト 5.3 に示すように、 DECLARE SECTION は EXEC SQL BEGIN キーワードで始まり、EXEC SQL END キーワード で終わります。 EXEC SQL BEGIN DECLARE SECTION; sqlint32 hempno; /* to store employee id */ char hfirstname[20]; /* to store employee first name */ char hlastname[20]; /* to store employee last name */ char hedlevel[4]; /* to store employee education level */ double hsalary ; /* to store employee salary */ double hnewsalary; /* to store employee new salary */ char hdynstmt[16384]; /* to store SQL statements*/ EXEC SQL END DECLARE SECTION; リスト 5.3 – ホスト変数の宣言 5.3.4.3 データベースに接続する データベース上での操作をする前に、接続を確立する必要があります。データベース接続は、暗 黙的もしくは明示的に確立されます。暗黙的な接続では、ユーザーID は現行のユーザーID であ るとみなされます。明示的な接続では connect ステートメントのなかでユーザーID とパスワードを 指定する必要があります。C/C++アプリケーションでは、暗黙的な接続は以下のステートメントを実 行することによって確立できます。 EXEC SQL CONNECT TO sample; 明示的な接続をしたい場合には以下のステートメントを使用します。 EXEC SQL CONNECT TO sample USER administrator USING admin123; リスト 5.4 はエラー処理を伴う connect ステートメントを示しています。 (1) EXEC SQL CONNECT TO sample; /* Database name is SAMPLE*/ (2) if (SQLCODE < 0) { printf ("\n ERROR WHILE DATABASE CONNECTION\n"); printf ("\n SQLCODE = %d", SQLCODE); 174 DB2 アプリケーション開発入門 rc = 1; exit(1); } else { printf ("\n CONNECT TO DATABASE SUCCESSFULLY\n"); } リスト 5.4 – データベースへの接続 リスト 5.4 のそれぞれの項目をみていきましょう。 1. このステートメントで sample データベースに接続を確立しています。 2. このステートメントでは接続が成功したかどうかを検証しています。SQLCODE は、ステー トメントが実行された後にセットされる DB2 の特別な変数です。SQLCODE が 0 より小さ い場合、ステートメントはエラーで終了しています。SQLCODE が 0 であれば、ステートメ ントは成功しており、0 より大きい場合には、警告と共に終了しています。 表 5.9 は上記のコード・スニペットの出力を示しています。 図 5.9 – connect ステートメントの出力 utilemb.h ヘッダー・ファイルをインクルードすると、データベースに接続するためのサンプル・プロ グラムとして提供されいてる DbConn ユーティリティーを使用することもできます。 (1) rc = DbConn(dbAlias, user, pswd); (2) if (rc != 0) { printf("\n Error while connecting to database"); return rc; } リスト 5.5 –DbConn ユーティリティー関数を使用してデータベースに接続する リスト 5.5 のそれぞれの項目についてみていきましょう。 1. このステートメントは DbConn ユーティリティー関数を使用して sample データベースに 接続を確立しています。 2. このステートメントは接続が成功したかどうかを検証しています。 注: C の DB2 サンプル・プログラムに含まれるユーティリティー関数は、<DB2 インストール・パス 第 5 章 - C/C++でのアプリケーション開発 175 >\sqllib\samples\c(Windows の場合)や<DB2 インストール・パス>/sqllib/samples/c (Linux の 場合)にあります。C++の場合は"cpp"というサブ・ディレクトリーを探して下さい。Windows の場合 なら、<DB2 インストール・パス>\sqllib\samples\cpp にあります。 5.3.4.4 SQL ステートメントを実行する SQL ステートメントを実行するためには、SQL ステートメントの始まりであることを示すために EXEC SQL キーワードが必要で、これはセミコロン(;)で終わる必要があります。この節ではどのよう に静的および動的 SQL を実行し、INSERT, SELECT, UPDATE, DELETE のような異なる操作 をどのように実行するのかを示します。 5.3.4.4.1 表へのデータの挿入 以 下 の リ ス ト 5.6 に て 説 明 さ れ る AddEmployeeInfo() 関 数 を み て く だ さ い 。 こ の 関 数 は EMPLOYEE 表に従業員情報を挿入するために使用されています。 int AddEmployeeInfo() { int rc = 0; printf("\n========================="); printf("\n ADD EMPLOYEE INFORMATION"); printf("\n========================="); (1) EXEC SQL INSERT INTO employee(empno, firstnme, lastname, edlevel, salary) VALUES (50001, 'RAUL', 'CHONG', 21, 6000), (50002, 'JAMES', 'JI', 20, 5786), (50003, 'MIN', 'YAO', 20, 5876), (50004, 'IAN', 'HAKES', 19, 5489), (50005, 'VINEET', 'MISHRA', 19, 5600); (2) if(SQLCODE < 0) { printf ("\n ERROR WHILE ADDING EMPLOYEE INFORMATION"); printf ("\n RETURNED SQLCODE = %d", SQLCODE); rc = -1 } else { printf("\n EMPLOYEE ADDED SUCESSFULLY "); EXEC SQL COMMIT; } return rc; } リスト 5.6 – 従業員情報の挿入 176 DB2 アプリケーション開発入門 リスト 5.6 のそれぞれの項目についてみていきましょう。 1. このステートメントは employee 表に従業員情報を挿入しています。 2. このステートメントは挿入が成功したかどうかを検証しています。 表 5.10 は上記のコード・スニペットの出力です。 図 5.10 –INSERT 操作の出力 5.3.4.4.2 表からのデータの取得 データの取得には SELECT ステートメントを使用します。SELECT ステートメントが 1 行を返す場 合、ホスト変数に結果を直接保管するために INTO 節(SELECT INTO)を使用します。 SELECT が複数行を返す場合は、カーソルを使用して 1 行ずつ取り出す必要があります。カーソ ルは、アプリケーション・プログラム内で行のセットの中の特定の行を指すために使用される制御構 造です。カーソルによる作業は以下のステップとなります。 1. DECLARE CURSOR ステートメントを使用してカーソルを宣言します 2. OPEN ステートメントを使用してカーソルをオープンします 3. FETCH ステートメントを使用して 1 行ずつ行を取得します 4. CLOSE ステートメントを使用してカーソルを終了します リスト 5.7 の、データを取得するサンプルである FetchEmployeeInfo()関数をみてみましょう。こ の関数は、EMPLOYEE 表から ID が 50001 から 50005 の間の従業員の従業員情報を取得して います。 int FetchEmployeeInfo() { int rc = 0; (1) EXEC SQL DECLARE cur1 CURSOR FOR SELECT empno, firstnme, lastname, edlevel, salary FROM employee WHERE empno BETWEEN 50001 AND 50005; if(SQLCODE < 0) { 第 5 章 - C/C++でのアプリケーション開発 177 printf ("\n ERROR WHILE CURSOR DECLARATION"); printf ("\n RETURNED SQLCODE = %d", SQLCODE); rc = -1; exit(1); } (2) /* open cursor */ EXEC SQL OPEN cur1; /* fetch cursor */ EXEC SQL FETCH cur1 INTO :hempno, :hfirstname, :hlastname, :hedlevel, :hsalary ; printf("\n\nEMPNO FIRSTNAME LASTNAME EMPSALARY"); printf("\n----- --------- -------- -----------\n"); while (SQLCODE != 100) { printf("%d %10s %11s %15f \n", hempno, hfirstname, hlastname, hsalary); EXEC SQL FETCH cur1 INTO :hempno, :hfirstname, :hlastname, :hedlevel, :hsalary; if(SQLCODE < 0) { printf ("\n ERROR WHILE FETCHING DATA"); printf ("\n RETURNED SQLCODE = %d", SQLCODE); rc = -1; exit(1); } } (4) EXEC SQL CLOSE cur1; EXEC SQL COMMIT; return rc; } (3) リスト 5.7 – 従業員情報の選択 上記のリストでは以下を行っています。 1. カーソル cur1 の宣言 2. cur1 のオープン 3. 行を 1 行ずつ取り出し、値を表示 4. カーソルのクローズ 表 5.11 は上記コード・スニペットの出力です。 178 DB2 アプリケーション開発入門 図 5.11 –SELECT 操作の出力 5.3.4.4.3 表のデータの更新 リスト 5.8 の関数 UpdateEmployeeInfo()を確認し、どのように表のデータを更新するのかをみて いきましょう。 この例では、動的 SQL を使用しています。第 1 章の”DB2 アプリケーションの概要”で述べたように、 動的 SQL の場合、実行時まで SQL の構造に関しては全てが分かっているわけではありません。 ステートメントはパラメーター・マーカーを使用し、クエスチョン・マーク(?) によって、明らかになって いないパラメーターが示されます。PREPARE ステートメントが動的 SQL を”コンパイル”します。 int UpdateEmployeeInfo() { int rc = 0, noofemp, loop; printf("\n============================"); printf("\n UPDATE EMPLOYEE INFORMATION"); printf("\n============================"); (1) strcpy(hdynstmt, "UPDATE employee SET SALARY = ? WHERE empno = ?"); (2) EXEC SQL PREPARE stmt FROM :hdynstmt; if(SQLCODE < 0) { printf ("\n EROROR WHILE PREPARING STATEMENT"); printf ("\n RETURNED SQLCODE = %d", SQLCODE); rc = -1; exit(1); } printf("\n NUMBER OF EMPLOYEE TO UPDATE: "); scanf("\n%d", &noofemp); for(loop = 0; loop != noofemp; loop++) 第 5 章 - C/C++でのアプリケーション開発 179 { printf("\n ENTER EMPLOYEE ID AND NEW SALARY: "); scanf("\n %d %lf",&hempno, &hnewsalary); (3) EXEC SQL EXECUTE stmt USING :hnewsalary, :hempno; if(SQLCODE < 0) { printf ("\n EROROR WHILE EXECUTING STATEMENT"); printf ("\n RETURNED SQLCODE = %d", SQLCODE); rc = -1; exit(1); } } printf("\n EMPLOYEE INFORMATION UPDATED SUCESSFULLY "); (4) EXEC SQL COMMIT; if(SQLCODE < 0) { printf ("\n EROROR WHILE COMITTING DATA"); printf ("\n RETURNED SQLCODE = %d", SQLCODE); rc = -1; exit(1); } return rc; } リスト 5.8 – 従業員情報の更新 上記のリストでは、下記を実行しています。 1. SQL ステートメントを変数に割り当てます 2. パラメーター・マーカーと共にステートメントを準備します 3. ユーザーから入力されたホスト変数 hnewsalary と hempno を使用してステートメントを 実行します 4. トランザクションをコミットします 図 5.12 は上記のコード・スニペットの出力です。 180 DB2 アプリケーション開発入門 図 5.12 - SELECT 操作の出力 5.3.4.4.4 表からのデータの削除 EMPLOYEE 表からの従業員情報を削除する DeleteEmployeeInfo()関数をみていきましょう。リ スト 5.9 で削除の例を示しています。 int DeleteEmployeeInfo() { int rc = 0; int option; char diagoption; printf("\n============================"); printf("\n DELETE EMPLOYEE INFORMATION"); printf("\n============================"); printf("\n ENTER 1: (TO DELETE EMPLOYEE INFORMATION) "); printf("\n ENTER 2: (TO DELETE ALL EMPLOYEES INFORMATION) "); scanf("\n%d", &option); if(option == 1) { printf("\n ENTER EMPLOYEE ID:"); scanf("\n%d", &hempno); (1) EXEC SQL DELETE employee WHERE empno = :hempno; if(SQLCODE < 0) { printf ("\n EROROR WHILE DELETING INFORMATION"); printf ("\n RETURNED SQLCODE = %d", SQLCODE); rc = -1; exit(1); 第 5 章 - C/C++でのアプリケーション開発 181 } printf("\n EMPLOYEE WITH ID %d DELETED SUCESSFULLY ", hempno); } else { (2) EXEC SQL DELETE employee WHERE empno BETWEEN 50001 AND 50005; if(SQLCODE < 0) { printf ("\n EROROR WHILE DELETING INFORMATION"); printf ("\n RETURNED SQLCODE = %d", SQLCODE); rc = -1; exit(1); } printf("\n ALL EMPLOYEES DELETED SUCESSFULLY "); (3) EXEC SQL COMMIT; } return rc; } リスト 5.9 – 従業員情報の削除 上記のリストでは以下を実行しています。 1. 特定の従業員の情報を削除する SQL を実行します 2. 全ての従業員の情報を削除する SQL を実行します 3. トランザクションをコミットします 図 5.13 は上記のコード・スニペットの出力です。 182 DB2 アプリケーション開発入門 図 5.13 – DELETE 操作の出力 5.3.4.5 ステートメントのコミット SQL ステートメントを実行した後は、コード・ロジックにも依存しますが、コミットまたはロールバック のステートメントを実行する必要があります。リスト 5.10 はコミット・ステートメントを示しています。 EXEC SQL COMMIT; if (SQLCODE < 0) { printf ("\n COMMIT ERROR"); printf ("\n SQLCODE = %d", SQLCODE); exit(1); } リスト 5.10 – COMMIT ステートメント 5.3.4.6 データベースからの切断 データベースからの切断は、データベースを使用する作業の最後のステップです。リスト 5.11 は データベース接続を切断するステートメントを示しています。 /* Disconnect from the sample database */ EXEC SQL CONNECT RESET; /* Error handling to check whether disconnection is successful */ if (SQLCODE < 0) { 第 5 章 - C/C++でのアプリケーション開発 183 printf ("\n Error while disconnecting from database"); printf ("\n Returned SQLCODE = ", SQLCODE); exit (1); } else { printf ("\n DISCONNECT FROM SAMPLE DATABASE SUCCESSFULLY \n\n"); } リスト 5.11 – データベースからの切断 DbDisconn ユーティリティーを使用してデータベースから切断することもできます。このためには、 utilemb.h ヘッダー・ファイルをヘッダー・セクションでインクルードしている必要があります。 /* disconnect from database */ rc = DbDisconn(dbAlias); if (rc != 0) { return rc; } リスト 5.12 –DbDisconn ユーティリティーを使用してデータベースから切断する 5.3.5 C/C++ の組み込み SQL アプリケーションの構築 C/C++の組み込み SQL アプリケーションの構築は、コマンドラインから手動で実施するか、DB2 の提供するスクリプトを利用して行うことができます。この節では両方の方法について説明します。 5.3.5.1 コマンドラインからの C/C++の 組み込み SQL アプリケーションの構築 C/C++の組み込み SQL アプリケーションをコマンドラインから構築するには以下の手順を踏みま す。 1. PRECOMPILE コマンドを使用してアプリケーションをプリコンパイルします 2. バインド・ファイルを作成した場合(手順 1 の PRECOMPILE コマンドで BINDFILE オプ ションを使用します) 、アプリケーションのパッケージを作成するために、BIND コマンドを 実行してデータベースにこのファイルをバインドします 3. 修正済みアプリケーション・ソース・ファイルおよび組み込み SQL を含まないソース・ファ イルをコンパイルし、アプリケーション・オブジェクトファイルを作成します。 4. 実行可能プログラムを作成するために、link コマンドを使用して、アプリケーション・オブ ジェクト・ファイルと DB2 とホスト言語のライブラリーをリンクします これらの手順は以下の 図 5.14に図示されています。この図はdeveloperWorksの記事” DB2 packages: Concepts, examples, and common problems.”[4] のものです。 184 DB2 アプリケーション開発入門 図 5.14 – 組み込み C/C++ SQL プログラムの構築 図 5.14 に示されている手順をそれぞれ詳しく見ていきましょう。 5.3.5.1.1 手順 1: ソース・ファイルのプリコンパイル 組み込み SQL アプリケーションのソース・ファイルを作成したら、PREP コマンドで SQL ステートメ ントを含むホスト言語ファイルをそれぞれプリコンパイルしなければいけません。プリコンパイラーは ソース・ファイルに含まれる全ての SQL ステートメントをコメント・アウトし、それらのステートメントに 対する DB2 ランタイム API 呼び出しを生成し、以下に示すような BINDFILE オプションが使用さ れている場合はバインド・ファイルを作成します。 db2 prep embeddedC.sqc bindfile 図 5.15 は上記のコマンドの出力です。 第 5 章 - C/C++でのアプリケーション開発 185 図 5.15 –C ソース・ファイルを PREP コマンドを使用してプリコンパイルする 5.3.5.1.2 手順 2: バインド・ファイルをバインドする バインドは、PREP コマンドによって作成されたバインド・ファイル(.bnd)のパッケージを、データベ ース・サーバー上に作成する処理です。バインド・ファイルは、コレクション ID、パッケージ名、タイ ムスタンプ、ホスト変数、SQL ステートメントなどのサーバー上にパッケージを作成するために DB2 が必要とする情報を含んでいます。以下は実行例です。 db2 bind embeddedC.bnd 図 5.16 は上記のコマンドの出力です。 図 5.16 – BIND コマンドを使用してパッケージをバインドする DB2 はバインド・ファイルの内容を出力できる db2bfd と呼ばれるツールも提供しています。このツ ールは、パッケージを実際に作成することなく、作成されるであろうパッケージに関する情報を取得 したい場合に役立ちます。 db2bfd -b はパッケージ名やパッケージ整合性トークンなどのヘッダー情報を出力します。これを 図 5.17 にて示します。 186 DB2 アプリケーション開発入門 図 5.17 –db2bfd –b の出力 図 5.18 に示すように、db2bfd -s は SQL ステートメントを出力します。 図 5.18 –db2bfd –s の出力 第 5 章 - C/C++でのアプリケーション開発 187 図 5.19 に示すように、db2bfd -v はホスト変数を出力します。 図 5.19 –db2bfd –v の出力 5.3.5.1.3 手順 3: 手順 2 で生成した変更済みソース・ファイル (.c) をコンパイルする C/C++コンパイラーを使用して、.c ファイルをコンパイルします。以下は実行例です。 cl -Zi -Od -c -W2 -DWIN32 embeddedC.c 図 5.20 は上記のコマンドの出力です。 図 5.20 – アプリケーションのコンパイル 5.3.5.1.4 手順 4: DB2 と C ライブラリーをファイルにリンクする .obj ファイルと DB2 および C ライブラリーを以下のようにリンクします。 link -debug -out:embeddedC.exe embeddedC.obj db2api.lib 図 5.21 は上記コマンドの出力です。 188 DB2 アプリケーション開発入門 図 5.21 – アプリケーションと DB2 ライブラリーのリンク 5.3.5.1.5 手順 5: アプリケーションの実行 手順 4 の結果、実行可能ファイル embeddedC ができます。Windows の場合は実行可能ファイ ルの名前を入力することで実行ができ、Linux の場合は実行可能ファイルとするために chmod +x によって属性を変更します。 embeddedC 図 5.22 は上記コマンドの実行例です。 図 5.22 – 実行可能ファイル embeddedC の出力 5.3.5.2 サンプル・ビルド・スクリプトを使用して組み込み SQL C/C++アプリケーションを構築する 組み込み C アプリケーションを構築するために、最も簡単な方法は、DB2 から提供されている bldapp スクリプトを使用することです。このスクリプトは、C で書かれたアプリケーション用は sqllib/samples/c ディレクトリーにあります。アプリケーションが C++で書かれている場合は、スクリ プトと、これらのファイルと共にビルドできるサンプル・ユーティリティー・プログラムが sqllib/samples/cpp にあります。 bldapp は 4 つのパラメーターをとり、スクリプト内では$1,$2,$3,$4 として参照されます。パラメー ター$1 には、ソース・ファイル名を指定します。組み込み SQL プログラムを構築する際にはデータ ベースへの接続が必要となるため、3 つの任意のパラメーターが提供されています。2 番目の引数 第 5 章 - C/C++でのアプリケーション開発 189 $2 は、接続したいデータベース名を指定し、3 番目の$3 にはデータベースのユーザーID を、$4 にはパスワードを指定します。 プログラムが組み込み SQL を含む場合、拡張子.sqc によって示されますが、この場合、embprep スクリプトがプリコンパイルのために呼ばれ、拡張子.c のファイルを生成します。 以下の例は組み込み C アプリケーションをどのように構築し実行するかを示しています。上記のサ ンプル・プログラム embeddedC.sqc を構築するためには、以下を入力します。 bldapp embeddedC 図 5.23 はその出力を示しており、5.4.1 で説明した 4 つの手順を赤線で囲っています。 図 5.23 – bldapp スクリプトを使用してアプリケーションを構築した出力 この結果として、実行可能ファイル embeddedC が生成されます。ファイル名を入力することでこの ファイルを実行できます。 embeddedC 190 DB2 アプリケーション開発入門 5.5 ODBC/CLI で C/C++ アプリケーションを開発する 1.3.3 節 で ODBC/CLI での開発を紹介しました。この章ではこの件についてより詳細に説明しま す。DB2 コール・レベル・インターフェース(DB2 CLI)はデータベース・サーバーの DB2 ファミリー に対する IBM の SQL インターフェースです。これは関数の引数として動的 SQL ステートメントを 渡して関数呼び出しを行い、リレーショナル・データベースにアクセスする為の、C および C++アプ リーションのプログラミング・インターフェースです。DB2 CLI はマイクロソフトのオープン・データー ベース・コネクティビティ(ODBC)の仕様と、SQL/CLI の国際標準に基づいています。DB2 CLI ドラ イバーは 1.3.3 節 で説明したように、全ての DB2 サーバーおよびいくつかのクライアントに含まれ ています。これは DB2 に接続する ODBC アプリケーションにとって、ODBC ドライバーとして動作 します。 ODBC は、組み込み動的 SQL の代替方法となりますが、組み込み SQL とは違って、ホスト変数 やプリコンパイラーを必要としません。組み込み SQL の C/C++アプリケーションに対する ODBC アプリケーションの主な利点は、ODBC アプリケーションは異なるベンダーによるさまざまなデータ ベースに対して、それぞれでコンパイルをすることなく実行ができる点です。コンパイルされた ODBC/CLI アプリケーションを実行するためには、アプリケーションを実行するマシンおよびクライ アントに、そのベンダーから提供される ODBC/CLI ドライバーをインストールさえすればよいので す。アプリケーションは実行時にプロシージャー呼び出しを使用して、データベースに接続し、 SQL ステートメントを実行し、データとステータス情報を取得します。 5.5.1 CLI/ODBC アプリケーションのための追加の環境設定 5.2 節 で説明したものに追加して、DB2 データベースにアクセスする ODBC/CLI アプリケーション のために、以下の手順も必要になります。 5.5.1.1 Linux 1. ODBC ドライバー・マネージャーをインストールします。 2. DB2 データベースを、.odbc.ini ファイル内の ODBC データ・ソースとして登録します。 たとえば、SAMPLE データベースを登録する場合、.odbc.ini ファイルは以下の表を 含む必要があります。 SAMPLE=IBM DB2 ODBC DRIVER 3. LD_LIBRARY_PATH 環境変数に、libodbc.so を設定します。 4. ODBCINI 環境変数を、以下のように設定します。 ODBCINI=/opt/odbc/system_odbc.ini;export ODBCINI 5.5.1.2 Windows 11. Microsoft の ODBC ドライバー・マネージャーと DB2 CLI/ODBC ドライバーがインストー ルされていることを確かめます。マシン上にそれぞれが存在していることを以下の手順で 確認します。 第 5 章 - C/C++でのアプリケーション開発 191 - 管理ツール内のデータ ソース(ODBC)のアイコンをダブルクリックするか、コマンドラ インから odbcad32.exe を実行します。 - ドライバタブをクリックし、IBM DB2 ODBC DRIVER - <DB2 コピー名> が表示され て い る か を 確 認 し ま す 。 Microsoft ODBC Driver Manager ま た は IBM DB2 CLI/ODBC ドライバーがインストールされていない場合には、 Windows オペレーテ ィング・システム上で DB2 インストールを再実行し、ODBC コンポーネントを選択しま す。 Windows オペレーティング・システムでは、インストール時に ODBC コンポーネ ントが手操作で選択解除されない限り、これらの製品は両方とも DB2 データベース 製品と一緒にインストールされます。 図 5.24 –ODBC データ・ソースの追加 2. 次は ODBC データ・ソースを構成します。以下に従いデータ・ソースを設定します。 • ODBC データ・ソース・アドミニストレーターパネル(図 5.24)で、システム DSN タ ブをクリックします。 • 「追加」をクリックして IBM DB2 ODBC ドライバーを選択し、完了をクリックして新 しいデータ・ソースを作成します。 192 DB2 アプリケーション開発入門 • ポップアップしたウィンドウ内に、任意のデータ・ソース名を入力し(この例では sample を使用します)、データベース SAMPLE を選択して追加ボタンをクリック し、このデータベースを登録します。 3. DB2 データベースが登録されたかどうかは、以下のコマンドを DB2 コマンド・ウィンド ウまたは Linux シェル上から実行して現在のデータ・ソースを表示することでも確認できま す。 db2 list system odbc data sources 図 5.25 は上記コマンドの出力です。リストにデータ・ソース SAMPLE が追加されていることが 分かります。 図 5.25 –ODBC データ・ソースの追加 • ODBC データ・ソース・アドミニストレーターを使用する以外に、データベースを 登録するには、以下のコマンドを使用します。 db2 catalog system odbc data source sample 5.5.2 ハンドル ODBC/CLI ハンドルとは、ODBC/CLI によって割り振られて管理されるデータ・オブジェクトを参照 する変数のことです。簡単に言うと、ハンドルはプログラムの各部分の間で変数への参照を受け渡 しするために使われるポインター変数です。ODBC/CLI ではハンドルには 4 つのタイプがあります。 環境ハンドル (SQL_HANDLE_ENV) 環境ハンドルは、アプリケーションのグローバル状態に関する情報 (属性や有効な接続な ど) が入っているデータ・オブジェクトを指します。接続ハンドルを割り振るためには、その 前に環境ハンドルを割り振っておく必要があります。 接続ハンドル (SQL_HANDLE_DBC) 接続ハンドルは、特定のデータベースへの接続に関連する情報が入っているデータ・オ ブジェクトを指します。接続ごとに、別個の接続ハンドルを割り振る必要があります。ステー トメントまたは記述子ハンドルを割り振るためには、その前に接続ハンドルを割り振ってお く必要があります。 ステートメント・ハンドル (SQL_HANDLE_STMT) 第 5 章 - C/C++でのアプリケーション開発 193 ステートメント・ハンドルは、 1 つの SQL ステートメントの実行に関する情報を保持するオ ブジェクトを指します。SQL ステートメントを実行する前に、ステートメント・ハンドルは割り 振られて接続ハンドルと関連付けられていなければなりません。 記述子ハンドル (SQL_HANDLE_DESC) 記述子ハンドルは、結果セット内の列についての情報および SQL ステートメント内の動 的パラメーターについての情報が入っているオブジェクトを指します。 図 5.26 は 「 DB2 Express-C: The Developer Handbook for XML, PHP, C/C++, Java, and .NET」という IBM のレッドブック[5]からのもので、それぞれのハンドル間の関係を図示してい ます。 図 5.26 – CLI ハンドル 5.5.3 ODBC/CLI アプリケーションの開発手順 図 5.27 は ODBC/CLI アプリケーションを開発するために必要な手順を示しています。 194 DB2 アプリケーション開発入門 図 5.27 – ODBC/CLI アプリケーションに必要な手順 図 5.27 の手順は以下の節で詳しく記述します。 5.5.3.1 インクルード・ヘッダー・ファイル CLI でのアプリケーション開発を始めるにあたり、開発に必要となる CLI の定数、関数プロトタイプ、 データ構造を含んでいる sqlcli1.h ヘッダー・ファイルをインクルードする必要があります。 リスト 5.13 は CLI/ODBC アプリケーションに必要とされるヘッダー・ファイルです。 /* Include header files */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sqlcli1.h> リスト 5.13 – CLI アプリケーションに必要なヘッダー・ファイル 5.5.3.2 環境ハンドルの割り振り SQLAllocHandle API を使用して異なるハンドルを割り振ることができます。SQLAllocHandle() は 環境、接続、ステートメント、または記述子ハンドルを割り振る汎用関数です。 第 5 章 - C/C++でのアプリケーション開発 195 注: こ の 関 数 は 使 用 す べ き で な い 関 数 SQLAllocConnect() 、 SQLAllocEnv() 、 お よ び SQLAllocStmt() にとって代わる関数です。CLI/ODBC 関数の完全なリストは、こちらのリンクを 参照してください。 http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/ doc/r0000553.html リスト 5.14 は SQLAllocHandle API の構文を示しています。 SQLRETURN SQLAllocHandle( SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandlePtr); リスト 5.14 – SQLAllocHandle 関数の構文 関数 SQLAllocHandle は、ハンドルのタイプ(環境、接続、ステートメント、記述子) 、入力ハンド ル、出力ハンドルを引数としてとります。環境ハンドルを割り振るためには HandleType の値は SQL_HANDLE_ENV でなければいけません。ハンドルタイプが SQL_HANDLE_ENV であれば、 入力ハンドルの値は SQL_NULL_HANDLE となります。OutputhandlePtr はバッファーを指すポ インターで、そのバッファーの中で、新規に割り振られたデータ構造にハンドルが返されます。ハン ドルが割り振られた後、SQLAllocHandle は下記のいずれかの、戻りコードを返します。これらの意 味は、読んで字の通りです。 SQL_SUCCESS SQL_SUCCESS_WITH_INFO SQL_INVALID_HANDLE SQL_ERROR 以下の例を見てみましょう。リスト 5.15 は環境ハンドルの割り振りを示しています。 /* allocate an environment handle */ (1) rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, pHenv); (2) if (rc != SQL_SUCCESS) { printf("\n\nERROR while allocating environment handle.\n"); funcRc = 1; exit (1); } printf("\n\nAllocate environment handle successfully."); リスト 5.15 – SQLAllocHandle 関数を使用して環境ハンドルを割り振る 上記のリストでは以下を実行しています。 196 DB2 アプリケーション開発入門 1. このステートメントは SQLAllocHandle API を使用して環境ハンドルを割り振り、 pHenv にそのポインターを返します。 2. このステートメントは割り振りが成功したかどうかを確認しています。 5.5.3.3 データベースへの接続 環境ハンドルの割り当てが成功したら、次は SQLConnect()を使用してデータベースに接続しま す。データベースに接続する前に、接続ハンドルを割り振る必要があります。接続ハンドルの割り 振りは、ハンドルのタイプを SQL_HANDLE_DBC として SQLAllocHandle API によって行いま す。リスト 5.16 は SQLConnect の構文を示しており、リスト 5.17 は SQLAllocHandle を使用 した接続ハンドルの割り振りおよび SQLConnect を使用したデータベースへの接続の例です。 SQLRETURN SQLConnect ( SQLHDBC ConnectionHandle, /* hdbc */ SQLCHAR *ServerName, /* szDSN */ SQLSMALLINT ServerNameLength, /* cbDSN */ SQLCHAR *UserName, /* szUID */ SQLSMALLINT UserNameLength, /* cbUID */ SQLCHAR *Authentication, /* szAuthStr */ SQLSMALLINT AuthenticationLength); /* cbAuthStr */ リスト 5.16 – SQLConnect 関数の構文 /* allocate a database connection handle */ (1) rc = SQLAllocHandle(SQL_HANDLE_DBC, *pHenv, pHdbc); if (rc != SQL_SUCCESS) { printf("\n\nERROR while allocating connection handle.\n"); funcRc = 1; exit (1); } printf("\n\nAllocate Connection handle successfully."); /* connect to the database */ (2) rc = SQLConnect(*pHdbc, (SQLCHAR *)dbAlias, SQL_NTS,(SQLCHAR *)user,SQL_NTS,(SQLCHAR *)pswd, SQL_NTS); if (rc != SQL_SUCCESS) { printf("\n\nERROR while connecting to database.\n"); funcRc = 1; exit (1); } 第 5 章 - C/C++でのアプリケーション開発 197 printf("\n\nConnected to %s database successfully\n", dbAlias); リスト 5.17 – 接続ハンドルの割り振りとデータベースへの接続 上記のリストでは以下を実行しています。 1. このステートメントは SQLAllocHandle 関数を使用して接続ハンドルを割り振ってい ます。 2. このステートメントは SQLConnect を使用してデータベースに接続しています。デー タベース名が引数として渡されます。 上記のコード・スニペットをテストする場合、cli_odbc.c(本書に添付)プログラムから ApplInit 関数 をコピーし、プログラム内のユーザーID とパスワードを変更してください。プログラムには、 リスト 5.15 や 5.17 に示されるようなハンドルの割り振りや接続のステートメントが含まれています。図 5.28 はリスト 5.15 と 5.17 のコード・スニペットの出力を示しています。 図 5.28 – 接続ハンドルの割り振りとデータベースへの接続 データベースへの接続には他の API も利用することができます。SQLDriverConnect() API は SQLConnect()の機能を拡張しており、追加の接続パラメーターとユーザーからの接続情報を取 得する機能が追加されています。表 5.4 は利用可能な接続関連の API です。 CLI 接続 API API の用途 SQLConnect ターゲット・データベースへの接続の確立 SQLBrowseConnect データ・ソースに接続するために必要な属性の取得 SQLSetConnectAttr 接続属性の設定 SQLGetConnectAttr 現在の属性の設定の取得 SQLDisconnect データ・ソースからの切断 表 5.4 – 接続関連の CLI API 大規模なアプリケーションにおいて、上記の手順を毎回実行することは非常に時間がかかります。 より簡単な方法として、samples ディレクトリーにある DB2 が提供するユーティリティー関数を使用 198 DB2 アプリケーション開発入門 することができます。アプリケーションのヘッダー・セクション内で、utilcli.h ヘッダー・ファイルをイン クルードする必要があります。ユーティリティー関数 CLIAppInit()を使用して、環境ハンドルや接 続ハンドルの割り振り、自動コミットの設定、データベースへの接続を行う例を見てみましょう。リスト 5.18 にこれを示します。 /* initialize the CLI application by calling a helper utility function defined in utilcli.c */ rc = CLIAppInit(dbAlias, user, pswd, &henv, &hdbc, (SQLPOINTER)SQL_AUTOCOMMIT_ON); if (rc != 0) { return rc; } リスト 5.18 – ユーティリティー関数を使用して CLI アプリケーションを初期化する 上記のコードは、データベース名(別名)、ユーザーID、パスワード、環境ハンドルおよび接続ハン ドルの変数を引数として CLI アプリケーションの初期化を行っています。 5.5.3.4 SQL ステートメントの実行 CLI では、SQL ステートメントを実行するために、まずステートメント・ハンドルを割り振る必要があり ます。ステートメント・ハンドルは接続ハンドルと関連づけられ、SQL ステートメントの実行を管理し ます。SQL ステートメントの実行には 4 つの手順が必要です。 1. ステートメント・ハンドルの割り振り 2. SQL ステートメントの準備と実行 3. 結果行の処理 4. 割り振ったステートメント・ハンドルの解放 図 5.29 は SQL ステートメントの実行に必要な手順を図示しています。 第 5 章 - C/C++でのアプリケーション開発 199 図 5.29 – SQL ステートメントの実行 SQL ステートメントは SQLCHAR 文字列の変数として DB2 CLI 関数に渡されます。この SQL ス テートメントにはパラメーター・マーカーが含まれる場合と含まれない場合があります。 リスト 5.19 はその例を示しています。 /* SQL INSERT statement to be executed */ SQLCHAR *stmt = (SQLCHAR *)"INSERT INTO employee(empno, firstnme, lastname, edlevel, salary) VALUES (50006, 'SANJAY', 'KUMAR', 21, 50000), (50007, 'RAJIT', 'PILLAI', 19, 47860), (50008, 'PRIYANKA', 'JOSHI', 20, 45600)"; リスト 5.19 –SQL ステートメントを文字列型変数に格納する 上記の例では、stmt 変数に INSERT ステートメントを割り当てています。変数を使わず、 SQLCHAR *にキャストした SQL 文字列を関数に引数として渡し、直接 SQL を使用することもで きます。リスト 5.20 では、SQLExecDirect で直接 SQL ステートメントを使用しています。 /* SQL INSERT statement to be executed */ SQLExecDirect (hstmt, (SQLCHAR *) " INSERT INTO employee(empno, firstnme, lastname, edlevel, salary) " "VALUES (50006, 'SANJAY', 'KUMAR', 21, 50000), " "(50007, 'RAJIT', 'PILLAI', 19, 47860), " "(50008, 'PRIYANKA', 'JOSHI', 20, 45600)", SQL_NTS); リスト 5.20 – 関数内で直接 SQL ステートメントを使用する 200 DB2 アプリケーション開発入門 表 5.5 は SQL ステートメントの実行をするためのサポートされる CLI API のリストです。 CLI API API の用途 SQLPrepare ステートメントを準備します SQLBindParameter パラメーター・マーカーをバッファーにバインドします SQLSetParam パラメーター・マーカーをバッファーにバインドします SQLDescribeParam パラメーター・マーカーの記述を返します SQLExecute ステートメントを実行します SQLExecDirect ステートメントを直接実行します SQLNumParams SQL ステートメント内のパラメーターの数を取得します SQLNumResultCols 結果の列数を取得します SQLBindCol 結果内の列をアプリケーション変数にバインドします SQLFetch 次の行をフェッチします SQLGetDiagField 診断データのフィールドを取得します SQLEndTran 接続または環境のトランザクションを終了します 表 5.5 – SQL ステートメント処理を行うサポートされる CLI API のリスト 注: このリストは完全ではありません。サポートされる CLI API の詳細および最新の情報に関しては、 DB2 9.7 のインフォメーション・センターを参照してください。 http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/ doc/r0000553.html 以下の例では、表 5.5 の INSERT、SELECT 、DELETE 操作についてどのように CLI API を使 用するかを実演します。 5.5.3.4.1 データの挿入 第 5 章 - C/C++でのアプリケーション開発 201 関数 AddEmployeeInfo()は EMPOLYEE 表に新しい従業員情報を追加します。INSERT SQL ステートメントを直接実行するには、リスト 5.21 に示すように、SQLExecDirect CLI 関数を使用し ます。 /* Perform INSERT operation */ int AddEmployeeInfo(SQLHANDLE hdbc) { int funcRc = 0; SQLRETURN rc = SQL_SUCCESS; SQLHANDLE hstmt; /* statement handle */ /* SQL INSERT statement to be executed */ (1) SQLCHAR *stmt = (SQLCHAR *)"INSERT INTO employee(empno, firstnme, lastname, edlevel, salary) " "VALUES (50006, 'SANJAY', 'KUMAR', 21, 50000), " "(50007, 'RAJIT', 'PILLAI', 19, 47860)," "(50008, 'PRIYANKA', 'JOSHI', 20, 45600)"; /* allocate a statement handle */ (2) rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if(rc != SQL_SUCCESS) { printf("\n Error while allocating statement handle"); funcRc = 1; exit (1); } /* execute the statement */ (3) rc = SQLExecDirect(hstmt, stmt, SQL_NTS); if(rc != SQL_SUCCESS) { printf("\n Error while statement execution"); funcRc = 1; exit (1); } /* Commit the transaction */ (4) rc = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT); if(rc != SQL_SUCCESS) { printf("\n Error while committing the transaction"); funcRc = 1; exit (1); 202 DB2 アプリケーション開発入門 } /* free the statement handle */ (5) rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if(rc != SQL_SUCCESS) { printf("\n Error while freeing handle"); funcRc = 1; exit (1); } printf("\n Employee added successfully "); return funcRc; } リスト 5.21 – 表へのデータの挿入 上記のリストでは以下を実行しています。 1. stmt 変数は SQL INSERT ステートメントを含んでいます。 2. SQLAllocHandle() API を使用してステートメント・ハンドルを割り振ります。接続ハ ンドルとステートメント・ハンドルの情報が引数として渡されています。 3. SQLExecDirect() API を使用してステートメントを直接実行します。ステートメント・ハ ンドルと stmt 変数が引数として渡されています。 4. SQLEndTran() API を使用してトランザクションをコミットします。接続ハンドル変数 と SQL_COMMIT が引数として渡されています。 5. SQLFreehandle() API を使用してステートメント・ハンドルを解放します。ステートメ ント・ハンドル変数が引数として渡されています。 図 5.30 は上記のコード・スニペットの出力です。 図 5.30- INSERT 操作の出力 5.5.3.4.2 データの取得 第 5 章 - C/C++でのアプリケーション開発 203 SELECT ステートメントの結果を取得するには、アプリケーション変数を結果セットの列にバインド することと、アプリケーション変数に行をフェッチすることを伴います。結果セットの行を取得するた めには以下が必要です。 a. 結果セットの列をそれぞれアプリケーション変数にバインドします。バインドは SQLBindCol()関数を使用して行います。 b. SQL_NO_DATA_FOUND が返るまで、SQLFetch()を呼んで結果セットのデータ 行を繰り返しフェッチします。 リスト 5.22 は従業員情報をどのようにフェッチするかを FetchEmployeeInfo()関数が示していま す。パラメーター・マーカーはクエスチョン・マーク(?) で表現されます。アプリケーションは SQL ス テートメントが実行される前に、それぞれのアプリケーション変数をパラメーター・マーカーにバイン ドしなければいけません。バインドは SQLBindParameter()の呼び出しによって実行されていま す。 /* perform Select operation */ int FetchEmployeeInfo(SQLHANDLE hdbc) { int funcRc = 0; SQLRETURN rc = SQL_SUCCESS; SQLHANDLE hstmt; /* statement handle */ (1) /* SQL SELECT statement to be executed */ SQLCHAR *stmt = (SQLCHAR *) "SELECT firstnme, lastname, edlevel FROM employee WHERE empno >= ? "; sqlint32 empno = 0; (2) struct { SQLINTEGER ind; SQLCHAR value[20]; } firstname; /* variable to be bound to the firstnme column */ struct { SQLINTEGER ind; SQLCHAR value[15]; } lastname; /* variable to be bound to the lastname column */ struct { SQLINTEGER ind; SQLSMALLINT value; 204 DB2 アプリケーション開発入門 } edlevel; /* variable to be bound to the edlevel column */ /* set AUTOCOMMIT OFF */ (3) rc = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_NTS); if(rc != SQL_SUCCESS) { printf("\n Error while handle allocation"); funcRc = 1; exit (1); } /* allocate a statement handle */ (4) rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if(rc != SQL_SUCCESS) { printf("\n Error while allocating statement handle "); funcRc = 1; exit (1); } /* prepare the statement */ (5) rc = SQLPrepare(hstmt, stmt, SQL_NTS); if(rc != SQL_SUCCESS) { printf("\n Error while preparing statement"); funcRc = 1; exit (1); } /* bind empno to the statement */ (6) rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &empno, 0, NULL); if(rc != SQL_SUCCESS) { printf("\n Error while binding paremeters"); funcRc = 1; exit (1); } /* execute the statement for empno = 50006 */ empno = 50006; 第 5 章 - C/C++でのアプリケーション開発 205 /* execute the statement */ (7) rc = SQLExecute(hstmt); if(rc != SQL_SUCCESS) { printf("\n Error while statement execution"); funcRc = 1; exit (1); } /* bind column 1 to variable */ (8) rc = SQLBindCol(hstmt, 1, SQL_C_CHAR, firstname.value, 20, &firstname.ind); if(rc != SQL_SUCCESS) { printf("\n Error while binding column"); funcRc = 1; exit (1); } /* bind column 2 to variable */ (9) rc = SQLBindCol(hstmt, 2, SQL_C_CHAR, lastname.value, 15, &lastname.ind); if(rc != SQL_SUCCESS) { printf("\n Error while binding column"); funcRc = 1; exit (1); } /* bind column 3 to variable */ (10) rc = SQLBindCol(hstmt, 3, SQL_C_SHORT, &edlevel.value, 0, &edlevel.ind); if(rc != SQL_SUCCESS) { printf("\n Error while binding column"); funcRc = 1; exit (1); } printf("\n\n FIRSTNAME printf(" ---------------- LASTNAME -------\n"); /* fetch each row and display */ EDLEVEL \n"); 206 DB2 アプリケーション開発入門 (11) rc = SQLFetch(hstmt); if (rc == SQL_NO_DATA_FOUND) { printf("\n Data not found.\n"); } while (rc != SQL_NO_DATA_FOUND) { printf(" %8s %14s %8d \n", firstname.value, lastname.value, edlevel.value); /* fetch next row */ rc = SQLFetch(hstmt); } /* Commit the transaction */ (12) rc = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT); if(rc != SQL_SUCCESS) { printf("\n Error while committing the transaction"); funcRc = 1; exit (1); } /* free the statement handle */ (13) rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if(rc != SQL_SUCCESS) { printf("\n Error while freeing handle"); funcRc = 1; exit (1); } return funcRc; } リスト 5.22 – 表からのデータのフェッチ 上記のリストでは以下を実行しています。 a. stmt 変数は SELECT ステートメントを含んでいます。 b. firstnme,lastname,edlevel 列にバインドされる変数です。 c. SQLSetConnectAttr 関数を使用して自動コミットをオフにしています。 d. SQLAllochandle 関数を使用してステートメント・ハンドルを割り振っています e. ス テ ート メ ン ト に パ ラ メ ータ ー ・ マ ーカ ー が あ る の で SQLPrepare を使 用 し て SELECT ステートメントを準備します 第 5 章 - C/C++でのアプリケーション開発 207 f. SQLBindParameter 関数を使用して empno 変数をステートメントにバインドしま す。 g. SQLExecute を使用して empno=50006 のステートメントを実行します h. SQLBindCol を使用して列 1 を変数 firstname にバインドします。 i. SQLBindCol を使用して列 2 を変数 lastname にバインドします。 j. SQLBindCol を使用して列 3 を変数 edlevel にバインドします。 k. SQLFetch を使用してそれぞれの行をフェッチし、結果を表示します。 l. SQLEndTran 関数を使用してトランザクションをコミットします。 m. SQLFreeHandle 関数を使用して、割り振ったステートメント・ハンドルを解放します。 図 5.31 は上記のコード・スニペットの出力です。 図 5.31 – 表から従業員情報をフェッチする 5.5.3.4.3 データの削除 リスト 5.23 は DeleteEmployeeInfo()を示しています。これは従業員情報を削除するために SQLExecDirect を呼び出しています。 /* Perform Delete operation */ int DeleteEmployeeInfo(SQLHANDLE hdbc) { int funcRc = 0; SQLRETURN rc = SQL_SUCCESS; SQLHANDLE hstmt; /* statement handle */ /* SQL DELETE statement to be executed */ (1) SQLCHAR *stmt = (SQLCHAR *)"DELETE FROM employee WHERE empno >= 50006"; 208 DB2 アプリケーション開発入門 /* set AUTOCOMMIT OFF */ (2) rc = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_NTS); if(rc != SQL_SUCCESS) { printf("\n Error while setting Auto Commit OFF"); funcRc = 1; exit (1); } /* allocate a statement handle */ (3) rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if(rc != SQL_SUCCESS) { printf("\n Error while allocating statement handle"); funcRc = 1; exit (1); } /* directly execute the statement */ (4) rc = SQLExecDirect(hstmt, stmt, SQL_NTS); if(rc != SQL_SUCCESS) { printf("\n Error while statement execution"); funcRc = 1; exit (1); } /* Commit the transaction */ 5) rc = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT); if(rc != SQL_SUCCESS) { printf("\n Error while committing transaction"); funcRc = 1; exit (1); } /* free the statement handle */ 6) rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); if(rc != SQL_SUCCESS) { printf("\n Error while freeing handle"); funcRc = 1; 第 5 章 - C/C++でのアプリケーション開発 209 exit (1); } printf("\n Employee Deleted successfully"); return funcRc; } リスト 5.23 – 従業員情報の削除 上記のリストでは以下を実行しています。 1. stmt 変数は DELETE ステートメントを含んでいます。 2. SQLSetConnectAttr 関数を使用して自動コミットをオフにしています。 3. SQLAllocHandle()関数を使用してステートメントを割り振っています。 4. SQLExecDirect() API を使用して delete SQL ステートメントを直接実行します。ス テートメント・ハンドルと stmt 変数が引数として渡されています。 5. SQLEndTran() API を使用してトランザクションをコミットします。接続ハンドル変数 と SQL_COMMIT が引数として渡されています。 6. SQLFreehandle() API を使用してステートメント・ハンドルを解放します。ステートメ ント・ハンドル変数が引数として渡されています。 図 5.32 は、上記のコード・スニペットの出力です。 図 5.32 – 表からの従業員情報の削除 5.5.3.5 データベースからの切断 SQL ステートメントの実行後は、次は SQLDisconnect()を呼んでデータベースから切断します。 リスト 5.24 はこれをどのように行うかを示しています。 /* disconnect from the database */ (1) rc = SQLDisconnect(*pHdbc); (2) if (rc != SQL_SUCCESS) { printf("\n\nERROR while disconnecting from database.\n"); 210 DB2 アプリケーション開発入門 funcRc = 1; exit (1); } printf("\n\nDisconnect from %s database successfully.", dbAlias); リスト 5.24 – データベースからの切断 上記のリストでは以下を実行しています。 1. SQLDisconnect API を使用してデータベースから切断します。コネクション・ハンド ル変数を引数として渡します。 2. 切断が成功したかどうかを確認します。 5.5.3.6 ハンドルの解放 CLI アプリケーションの最後のステップは、割り振ったすべてのハンドルを解放することです。割り 振ったハンドルを解放するために、DB2 CLI はハンドルタイプとハンドル変数を引数にとる SQLFreeHandle API を提供しています。SQLFreeHandle ()を呼ぶ前に、アプリケーションは SQLDisconnect() を 呼 ん で い な け れ ば い け ま せ ん 。 SQLDisconnect() を 呼 ぶ 前 に SQLFreeHandle()を呼ぶと SQL_ERROR が返り、接続は依然として残存します。リスト 5.25 は どのようにハンドルを解放するかを示しています。 /* free connection handle */ (1) rc = SQLFreeHandle(SQL_HANDLE_DBC, *pHdbc); if (rc != SQL_SUCCESS) { printf("\n\nERROR while freeing connection handle.\n"); funcRc = 1; exit (1); } printf("\n\nFree connection handle successfully.") ; /* free environment handle */ (2) rc = SQLFreeHandle(SQL_HANDLE_ENV, *pHenv); if (rc != SQL_SUCCESS) { printf("\n\nERROR while freeing environment handle.\n"); funcRc = 1; exit (1); } printf("\n\nFree environment handle successfully.\n\n") ; リスト 5.25 – 割り振られた環境および接続ハンドルを解放する 上記のリストでは以下を実行しています。 a. SQLFreehandle を使用して割り振られた接続ハンドルを解放します 第 5 章 - C/C++でのアプリケーション開発 211 b. SQLFreehandle を使用して割り振られた環境ハンドルを解放します 図 5.33 はリスト 5.24 と 5.25 のコード・スニペットの出力です。 図 5.33 – 割り振られたハンドルの解放 注: こ の 節 で 示 さ れ て い る コ ー ド ・ ス ニ ペ ッ ト は 本 書 に 添 付 さ れ て い る Exercise_Files_DB2_Application_Development.zip ファイルの cli_odbc.c プログラムから引用 されたものです。アプリケーションを構築する前に、プログラムの 52 行目と 53 行目のユーザーID とパスワードを変更してください。 5.5.4 ODBC/CLI アプリケーションの構築 ODBC/CLI アプリケーションの構築は、コマンドラインから手動で、もしくは DB2 の提供するスクリ プトを使用して行います。 5.5.4.1 ODBC または CLI アプリケーションをコマンドラインから構築する ODBCアプリケーションをコマンドラインから構築するには、以下の手順を実施します。 1) 以下のコマンドを使用して Windows 上のアプリケーションをコンパイルします。 cl -Zi -Od -c -W2 -DWIN32 cli_odbc.c 図 5.34 は上記コマンドの出力です。 212 DB2 アプリケーション開発入門 図 5.34 – アプリケーションのコンパイル 2) CLI アプリケーションの場合は CLI ライブラリー(db2cli.lib)をアプリケーションにリンクし、ODBC ア プリケーションの場合は ODBC ライブラリー(odbc32.lib)をリンクします。例えば、以下のコマンドは CLI アプリケーション cli_odbc を作成します。 link -debug -out:cli_odbc.exe cli_odbc.obj db2cli.lib db2api.lib 図 5.35 は上記コマンドの出力です。 図 5.35 – アプリケーションを CLI ライブラリーとリンクする 一方、以下のコマンドは ODBC アプリケーションを作成します。 link -debug -out:cli_odbc.exe cli_odbc.obj odbc32.lib 図 5.36 は上記コマンドの出力です。 図 5.36 – アプリケーションを ODBC ライブラリーとリンクする 実行ファイル名 cli_odbc を入力することで、このファイルを実行できます。 5.5.4.2 ODBC または CLI アプリケーションをサンプル・ビルド・スクリプトを使用して構築する DB2 より提供されるサンプル・スクリプト bldapp を使用してアプリケーションを構築するためには、 以前の節 5.4.2 で説明したのと同じ手順に従ってください。デフォルトでは bldapp スクリプトは CLI アプリケーションの構築のために db2cli.lib ライブラリーを使用します。bldapp を使用して 第 5 章 - C/C++でのアプリケーション開発 213 ODBC アプリケーションを構築したい場合は、スクリプト内の db2cli.lib を odbc32.lib に置き換えて ください。 以前にも記述したサンプル・プログラム cli_odbc を構築するためには、以下を入力してください。 bldapp cli_odbc この結果は、実行ファイル cli_odbc です。実行ファイル名を入力して実行できます。 cli_odbc 5.6 DB2 の C/C++ アプリケーション内で XML を処理する 第 2 章「DB2 pureXML」で説明したように、DB2 は XML データをネイティブに格納するために、 XML データ・タイプを提供しています。データベース・サーバーと組み込み SQL の C/C++アプリ ケーションとの間で XML データをやり取りするためには、アプリケーションのソースコード内でホス ト変数を宣言する必要があります。XML データ・タイプの列は、SQL_TYP_XML 列 SQLTYPE と して記述されます。XML 列には、SQL、SQL/XML 、または XQuery を使用して直接アクセスでき ます。 サンプル・プログラム xmlinsert.sqc、xmlread.sqc は、XML 列へのデータの挿入および読み出し の異なる方法を示しています。これらのプログラムは、<DB2 インストール・パス>/samples/xml/c にあります。 5.7 演習 1. データベースに接続し、データベースのログ・ファイルを非同期に読み取るプログラムを 書いてみましょう。 解答:<DB2 インストール・パス>/samples/c ディレクトリー以下にある、dblogconn.sqc を みてみましょう。 2. LOB データの読み取りおよび書き込みをするプログラムを書いてみましょう。 解答:<DB2 インストール・パス>/samples/c ディレクトリー以下にある、dtlob.sqc をみて みましょう。 3. 表のトリガーを使用するプログラムを書いてみましょう。 解答:<DB2 インストール・パス>/samples/c ディレクトリー以下にある、tbtrig.sqc をみて みましょう。 4. CLI LOAD ユーティリティーを使用してデータの挿入をするプログラムを書いてみましょう。 解答:<DB2 インストール・パス>/samples/c ディレクトリー以下にある、tbload.c をみてみ ましょう。 214 DB2 アプリケーション開発入門 5.8 まとめ この章では、DB2 での C/C++アプリケーションの開発の基礎について説明しました。この章では、 C/C++アプリケーション構築のための環境の構成方法や、組み込み SQL アプリケーションや CLI/ODBC アプリケーションを使用して DB2 データベースに接続して様々な種類の SQL ステー トメントを実行する方法について述べました。CLI/ODBC アプリケーションは実行時に関数呼び出 しを使って、データベースへの接続や SQL ステートメントの実行、データやステータス情報の取得 を行います。 5.9 確認問題 1. 組み込み SQL の C/C++アプリケーションと、CLI/ODBC アプリケーションの違いは何です か? 2. カーソルとは何ですか? 3. パラメーター・マーカーとは何ですか? 4. ハンドルとは何ですか? 5. CLI API によって戻される戻り値の違いは何ですか? 6. Windows での組み込み SQL の C++アプリケーションの拡張子は何ですか? 7. 8. A. .sqc B. .c C. .sqx D. .sqC E. 上記のいずれでもない バインド・ファイルから、SQL ステートメントを表示するコマンドは何ですか? A. db2bfd –b B. db2bfd –s C. db2bfd –h D. db2bfd –v E. 上記のいずれでもない 現在のデータ・ソースを表示するコマンドは何ですか? A. db2 list odbc data sources B. db2 system odbc data sources C. db2 list system odbc data sources D. db2 system odbc data source 第 5 章 - C/C++でのアプリケーション開発 215 E. 9. 上記のいずれでもない ハンドルを割り振るのは、以下のうちどの API でしょうか? A. SQLAllocHandle () B. SQLAllocConnect() C. SQLAllocEnv() D. SQLAllocStmt() E. 上記のいずれでもない 10. CLI アプリケーションでハンドルを割り振る順序として正しいものは、以下のうちどれでしょうか。 A. 環境ハンドルの割り振り -> 接続ハンドルの割り振り -> ステートメント・ハンドルの割り振 り-> ステートメント・ハンドルの解放 -> 接続ハンドルの解放 -> 環境ハンドルの解放 B. 接続ハンドルの割り振り -> 環境ハンドルの割り振り -> ステートメント・ハンドルの割り振 り-> ステートメント・ハンドルの解放 -> 環境ハンドルの解放 -> 接続ハンドルの解放 C. 接続ハンドルの割り振り -> 環境ハンドルの割り振り -> 環境ハンドルの解放 -> 接続ハ ンドルの解放 D. 環境ハンドルの割り振り -> ステートメント・ハンドルの割り振り-> ステートメント・ハンドル の解放 -> 環境ハンドルの解放 E. 上記のいずれでもない 6 第 6 章 – .NET によるアプリケーション開発 Microsoft は Windows プラットフォームでアプリケーションを作成および実行するプラットフォーム として .NET フレームワークを導入しました。これは Web 開発用、データベース接続、ユーザー・ インターフェースなど、多くの機能を提供するライブラリーを含んでいます。.NET では C# や Visual Basic をはじめとする多数の異なるプログラミング言語でコードを記述できます。どのプログ ラミング言語を使用しても .NET アプリケーションは中間言語 (IL) と呼ばれるバイト・コードにコンパ イルされ、共通言語ランタイム (CLR) で実行されます。CLR は .NET フレームワークの要であ り、.NET アプリケーションの実行環境を提供しています。 本章では、以下の内容についてご説明します。 DB2 用の.NET 環境のセットアップ ADO.NET 用の DataSet とプロバイダーの理解 IBM Visual Studio 用の IBM Database Add-In の操作 .NET を使った DB2 アプリケーションの開発 6.1.NET による DB2 アプリケーション: 全体像 .NET ではデータベース・アクセスは ActiveX Data Objects (ADO) for .NET を通じてサポートさ れます。ADO.NET は接続型と非接続型のデータベース・アクセスをサポートしています。.NET ア プリケーションによるデータベース接続は .NET データ・プロバイダーを必要とし、これは通常デー タベース・ベンダーから提供されます。 非接続型データ・アクセスでは、アプリケーションのメモリーに常駐する DataSet クラスのインスタ ンスがデータベースのキャッシュとして動作します。 Figure 6.1 provides an overview of .NET and DB2 applications. 図 6.1 は .NET と DB2 アプリケーションの概要を示しています。 218 DB2 アプリケーション開発入門 図 6.1 - .NET と DB2 アプリケーション この図は .NET アプリケーションが DB2 提供の .NET データ・プロバイダーを通じて DB2 データ ベースにアクセスしていることを表しています。非接続型アクセスでは DataSet オブジェクトが必要 です。 6.2 ADO.NET データ・アーキテクチャー ADO.NET によるデータ・アクセスは DataSet とデータ・プロバイダーによって行われます。 DataSet DataSet は非接続型の、メモリー上に展開されたデータ表現形式です。これはデータベ ースのある一部のローカル・コピーとして扱えます。DataSet はアプリケーションのメモリー 上に常駐し、その中のデータはデータベースとは独立して操作や更新可能です。DataSet 上での操作が完了すると、変更をデータベースに反映できます。DB2 などすべての有効 なデータ・ソースから DataSet にデータをロードできます。 データ・プロバイダー データ・プロバイダーは、データベース接続を提供し、これを維持します。各データ・プロバ イダーは効率的でパフォーマンスを意識したデータの提供を行う一連のコンポーネントで あり、以下のようなコンポーネント クラスによって構成されています。 - データベースへの接続機能を提供する Connection オブジェクト - コマンドの実行に使われる Command オブジェクト - 前方スクロールの読み取り専用な接続済みのレコードセットを提供する DataReader オブジェクト - 非接続の DataSet を保存したり、更新したりする DataAdapter オブジェクト 以下の図 6.2 は ADO.NET オブジェクト間の関係を示しています。これらのオブジェクトの詳細は 次の節で説明します。 第 6 章 – .NET によるアプリケーション開発 219 図 6.2 - ADO.NET コア・オブジェクトとそれぞれの関係 ADO.NET によるデータ・アクセスは、以下のように要約できます。 Connection オブジェクトがデータベースへの接続を確立します。Command オブジェクトがデー タベースへの照会を実行します。結果セットが返る場合、Command オブジェクトはカーソルのよう に DataReader オブジェクトを返します。もう一つの方法として、DataSet オブジェクトを保管する た め に DataAdapter が 利 用 で き ま す 。 デ ー タ ベ ー ス は Command オ ブ ジ ェ ク ト ま た は DataAdapter を使って更新されます。 6.2.1 ADO.NET 用のデータ・プロバイダー ADO.NET アーキテクチャーにおいて、アプリケーション (データ・コンシューマー) は、データベー ス (リソース) にデータ・プロバイダーを使って接続します。データ・プロバイダーはデータをカプセ ル化し、接続、SQL の実行、データの取り出しを含むデータベースを操作する手段を提供します。 DB2 アプリケーションが DB2 データベースへアクセスするには、以下の 3 種類の .NET データ・ プロバイダーが利用できます。 IBM Data Server Provider for .NET OLE DB .NET Data Provider ODBC .NET Data Provider 220 DB2 アプリケーション開発入門 IBM Data Server Provider for .NET は、IBM が提供するマネージド・コードで実装されたパフォ ー マ ン ス の良 い ADO.NET デ ー タ・プ ロ バ イ ダ ーです 。 こ のプ ロ バ イ ダ ーは OLE DB や ODBC .NET Data Provider よりもかなりよいパフォーマンスを提供します。 OLE DB .NET Data Provider は Microsoft が提供するブリッジ・ドライバーであり、ADO.NET リク エストを IBM OLE DB provider (IBMDADB2) に転送します。 ODBC.NET Data Provider は Microsoft が提供するブリッジ・ドライバーであり、ADO.NET リクエ ストを IBM ODBC ドライバーに転送します。 新規の ADO.NET アプリケーション開発では IBM Data Server Provider for .NET が推奨されま す。図 6-3 で示されるように、このドライバーは追加のソフトウェアレイヤーやブリッジを必要としな いため、最もよいパフォーマンスが得られます。 図 6.3 – DB2 アプリケーションで利用可能な .NET データ・プロバイダー 上 の 図 6.3 が 示 す よ う に 、 各 プ ロ バ イ ダ ー は 同 様 の 機 能 と 、 こ れ ま で に 紹 介 し た ク ラ ス (Connection, Command, DataAdapter, DataReader) を提供しています。 Microsoft の .NET Framework において、クラスはネーム・スペースと呼ばれる階層的なグループ で管理されます。ADO.NET で利用されるクラスはSystem.Data ネーム・スペースに含まれます。 IBM.Data.DB2 ネーム・スペースが IBM Data Server 用の .NET Framework データ・プロバイダ ーで使われます。IBM Data Server Provider for .NET は ADO.NET インターフェースを拡張し、 高速で安全なデータ・アクセスを提供します。 第 6 章 – .NET によるアプリケーション開発 221 注: ネーム・スペースの詳細は、以下のページを参照してください。 http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.swg.im.dbc lient.adonet.ref.doc/doc/IBMDataDB2Namespace.html 6.2.1.1 Connection オブジェクト ADO.NET では、Connection オブジェクトがデータベースへの接続やトランザクションの制御に 使われます。前節で紹介した 3 つのプロバイダーはそれぞれ独自の Connection オブジェクト (DB2Connection, OleDbConnection お よ び OdbcConnection) を 持 っ て い ま す 。 Connection オ ブ ジ ェ ク ト は デ ー タ ベ ー ス 接 続 で 必 要 と さ れ る 公 開 プ ロ パ テ ィ ー ConnectionString を持っています。ConnectionString プロパティーはデータベース名および ユーザー名/パスワードなどの接続パラメーターを必要とします。以下に例を示します。 connection.ConnectionString = “Database=Sample”; 表 6.2 で示されるように、ConnectionString プロパティーは Connection オブジェクトのコンスト ラクターで設定できます。 プロバイダー 例 IBM Data Server Provider for .NET DB2Connection connection = New DB2Connection(“Database=SAMPLE”); OLE DB .NET Data Provider OleDbConnection connection = new OleDbConnection(“Provider=IBMDADB2;" + Source=sample;UID=userid;PWD=password;”); ODBC.NET Data Provider OdbcConnection connection = new OdbcConnection("DSN=sample;UID=userid;PWD=password;"); 表 6.2 – データ・プロバイダーごとの接続文字列の例 表 6.3 は Connection オブジェクトの公開メソッドを説明しています。. メソッド名 説明 例 Open ConnectionString で指定され たデータベースへの接続を確 立します。 connection.Open(); 接続は Open メソッドを明示的 呼び出して確立することも、 DataAdapter を使って黙示的 に確立することもできます。 "Data 222 DB2 アプリケーション開発入門 Close データベース接続を切断しま す。 connection.Close(); CreateCommand Connection オブジェクトに関 連付けられた Command オブ ジェクトを返します。 connection.CreateCommand(); BeginTransaction トランザクションを開始します。 connection.BeginTransaction() 表 6.3 – Connection オブジェクトの公開メソッド 6.2.1.2 Command オブジェクト Command オブジェクトによって該当 Connection オブジェクト上でサポートされる SQL ステート メントやストアード・プロシージャーを実行できます。事前に Connection オブジェクトを作成する 必要がありますが、SQL ステートメントを作成する前に接続を確立する必要はありません。 Connamd オブジェクトは表 6.4 のようにインスタンス化できます。 プロバイダー 例 IBM Data Server Provider for .NET DB2Command cmd = new DB2Command(); OLE DB .NET Data Provider OleDbCommand cmd = new OleDbCommand(); ODBC.NET Data Provider OdbcCommand cmd = new OdbcCommand(); 表 6.4 – データ・プロバイダーごとの Command オブジェクトのインスタンス化方法 Command オブジェクトは CommandType と CommandText という公開プロパティーを持って います。CommandType は Command が SQL ステートメントを実行するか、ストアード・プロシ ージャーを実行するかを指定します。CommandText は実行される SQL ステートメントもしくはス トアード・プロシージャーを記述します。以下に例を示します。 cmd.CommandType = CommandType.Text; cmd.CommandText = "SELECT manager FROM org WHERE DEPTNUMB=10"; or cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = procName; Command オブジェクトには以下の公開メソッドがあります。 CreateParameter: パラメーターの操作に使用します。 第 6 章 – .NET によるアプリケーション開発 223 set param1 = cmd.CreateParameter("DEPTNAME", adVarChar, adParamInput, 14, "Test"); set param2 = cmd.CreateParameter("DEPTNUMB", adTinyInt, adParamInput, , 510); ExecuteNonQuery: UPDATE、INSERT や DELETE のような結果セットを返さない SQL の実行に使用します。このメソッドは、以下のように実行した操作によって影響を受け た行数を返します。 int rowsAffected = cmd.ExecuteNonQuery(); ExecuteReader: DataReader を返す SQL 照会の実行に使用します。DataReader は 前方スクロールのみ可能なデータストリームです。 DB2DataReader reader = cmd.ExecuteReader ( ); ExecuteScalar: 単一の値を取り出す SQL ステートメントの実行に使用します。 int count=(int)cmd.ExecuteScalar(); 注: cmd.ExecuteScalar() メソッドで返されるオブジェクトは、該当するデータベース・オブジェクトの型 にキャストしなければなりません。上の例は int 型の列から単一の値を取り出す場合に有効です。 6.2.1.3 DataAdapter オブジェクト DataAdapter オブジェクトは、データを含んだ非接続の DataSet を保持し、更新操作を行いま す。このオブジェクトは SELECT、INSERT、UPDATE および DELETE 用の 4 つのオプショナル なコマンドを含みます。このオブジェクトは、データベースと DataSet 間でデータを取り出したり、 戻したりするために使用します。 DataAdapter オブジェクトは表 6.5 で示される方法でインスタンス化されます。 プロバイダー 例 IBM Data Server Provider for .NET DB2DataAdapter adapter = new DB2DataAdapter(); OLE DB .NET Data Provider OleDbDataAdapter adapter = new OleDbDataAdapter(); ODBC.NET Data Provider OdbcDataAdapter adapter = new OdbcDataAdapter(); 表 6.5 – データ・プロバイダーごとの DataAdapter のインスタンス化方法 DataAdapter オブジェクトには以下の公開プロパティーがあります。 224 DB2 アプリケーション開発入門 DeleteCommand は DataSet からデータを削除する SQL ステートメントもしくはストアー ド・プロシージャーです。 adapter.DeleteCommand = new DB2Command(“DELETE From org WHERE DEPTNUMB= 10”, connection); InsertCommand は追加行を挿入する SQL もしくはストアード・プロシージャーです。 adapter.InsertCommand = new DB2Command(“INSERT INTO org VALUES (30,‘Test’, 60, ‘Eastern’, ‘Toronto’)”, connection); SelectCommand はデータベースの照会に使われる SQL もしくはストアード・プロシージ ャーです。 adapter.SelectCommand = new DB2Command(“SELECT manager FROM org WHERE DEPTNUMB = 30”, connection); UpdateCommand はデータベースの行を更新する SQL もしくはストアード・プロシージ ャーです。 adapter.UpdateCommand = new DB2Command(“UPDATE org SET manager=70 WHERE DEPTNUMB=20”, connection); DataAdapter には以下の公開メソッドがあります。 Fill: DataSet に行をロードします。 DataSet results= new DataSet(); adapter.SelectCommand = new DB2Command("Select * from dept", connection); adapter.Fill(results); Update: DataSet の中の行を更新し、INSERT、UPDATE および DELETE 操作によっ てデータベースを更新します。 DataSet results= new DataSet(); adapter.UpdateCommand = new DB2Command(“UPDATE org SET Manager=70 WHERE DEPTNUMB=20”, connection); adapter.Update(results); 6.2.1.4 DataReader オブジェクト DataReader はデータベース接続を伴い、SQL ステートメントやストアード・プロシージャーからの 結果セットによる高速な前方参照で使われます。DataReader オブジェクトは直接インスタンス化 できず、Command オブジェクトの ExecuteReader メソッドの返りとしてインスタンス化する必要 があります。 第 6 章 – .NET によるアプリケーション開発 225 DataReader オブジェクトは、以下の表 6.6 のように使用されます。 プロバイダー 例 IBM Data Server Provider for .NET Db2DataReader reader = cmd.ExecuteReader(); OLE DB .NET Data Provider OleDbDataReader reader = cmd.ExecuteReader(); ODBC.NET Data Provider OdbcDataReader reader = cmd.ExecuteReader(); 表 6.6 – データ プロバイダーごとの DataReader の使用方法 DataReader オ ブ ジ ェ ク ト に は FieldCount と HasRows 公 開 プ ロ パ テ ィ ー が あ り ま す 。 FieldCount プロパティーは現在行の列の数を返し、HasRows プロパティーは DataReader が 1 行以上の行を持つかどうかを true か false で返します。 int cols=reader.FieldCount; bool rows=reader.HasRows; DataReader オブジェクトには以下の公開メソッドがあります。 Read: 一度の呼び出しで 1 行を読み取り、カーソルを次の行に進めます。読み取る行が あった場合は true を、そうでない場合は false を返します。 bool done=reader.read(); Close: DataReader をクローズします。 reader.Close(); Getxxxx: xxxx 型のデータを取り出します。 Console.WriteLine (reader.GetString(1)); 6.2.2 ADO.NET の DataSet オブジェクト DataSet オブジェクトはデータベースから取り出され、メモリー上にキャッシュされたデータです。 DataSet は非接続型のデータ・セットであり、データ・ソースとは独立した整合性のあるリレーショナ ル・モデルを提供します。データベースと接続されていないため、データベース・サーバーとの接 続におけるオーバーヘッドが低減されます。DataSet オブジェクトの DataSetName 公開プロパ ティーによって、データ・セットの名前を設定したり、取り出すしたりすることができます。 DataSet ds = new DataSet(); ds.DataSetName = "DB2"; 226 DB2 アプリケーション開発入門 DataSet には以下の公開メソッドがあります。 AcceptChanges: DataSet の変更をコミットします。 ds.AcceptChanges(); Clear: DataSet の内容を消去します。 ds.Clear(); GetXML: DataSet に含まれるデータを XML 形式で取り出します。 Console.WriteLine(ds.GetXml()) ReadXML: XML スキーマとデータを DataSet に読み込みます。 ds.ReadXML(reader); WriteXML: DataSet から XML データを書き込みます。オプションでスキーマも書き込む ことができます。 ds.WriteXML ( ".\\test.xml" ) ; リスト 6.1 とリスト 6.2 は C# コードによる ADO.NET のサンプルであり、様々なデータ プロバイダ ーの使い方の例を示しています。それぞれのリストはデータベースに接続する C# コードです。こ れらのサンプルは DB2 の SAMPLE データベースが作成されていることを前提にしています。 リスト 6.1 は IBM Data Server .NET Data Provider を使った、データベース接続を行う C# コー ドの例です。 String connectString = "Database=SAMPLE"; DB2Connection conn = new DB2Connection(connectString); conn.Open(); return conn; リスト 6.1 – IBM Data Server Provider for .NET によるデータベース接続を行う C# コード リスト 6.2 は OLE DB .NET Data Provider を使った、データベース接続を行う C# コードの例で す。 OleDbConnection con = new OleDbConnection("Provider=IBMDADB2;" + "Data Source=sample;UID=userid;PWD=password;" ); con.Open() リスト 6.2 - OLE DB .NET Data Provider によるデータベース接続を行う C# コード リスト 6.3 は ODBC.NET Data Provider を使ったデータベース接続を行う C# コードの例です。 OdbcConnection con = new OdbcConnection("DSN=sample;UID=userid;PWD=password;"); con.Open() リスト 6.3 – ODBC.NET Data Provider によるデータベース接続を行う C# コード 第 6 章 – .NET によるアプリケーション開発 227 コード例は以下のコマンドでコンパイルできます。 csc NETSamp.cs /r:<DB2 Install Path>\bin\netf20\IBM.Data.DB2.dll ここで <DB2_Install_Path> は DB2 がインストールされたパスです。 C# ではすべてのエラーは例外のインスタンス化として扱われます。ADO.NET におけるエラー処 理は try/catch/finally ブロックもしくは On Error によって処理されます。 6.3 環境のセットアップ DB2 をアクセスする .NET アプリケーション開発を開始するにあたってのセットアップは非常に簡 単です。つまり、DB2 Client もしくは DB2 サーバー製品をインストールするだけです。表 6.1 は DB2 バージョン 9.7 に含まれる .NET データ プロバイダーと、各プロバイダーの 32 ビットおよび 64 ビットサポートを示しています。 IBM Data Server Provider for .NET Microsoft .NET Framework のバージョン と IBM Data Server Provider for .NET および Microsoft .NET Framework バージョン 2.0、バージョ ン 3.0、およびバージョン 3.5 32 ビットのサポー ト 64 ビットのサポー ト はい はい 表 6.1 - IBM Data Server Provider for NET によって提供される 32 ビットおよび 64 ビットのサ ポート DB2 サーバーまたはクライアントのインストール中、以下のいずれかの IBM Data Server Provider for .NET がインストールされます。 32 ビット AMD および Intel システム (x86) 用の Windows .NET Framework バージョン 2.0、3.0 および 3.5 用 IBM Data Server Provider for .NET の 32 ビット阪がインストールされます。 AMD64 および Intel 64 システム (x64) 用の Windows 64 ビット版の IBM Data Server Provider for .NET だけがインストールされます。64 ビッ ト版の IBM Data Server Provider for .NET は IA64 アーキテクチャーをサポートしませ ん。 32 ビット版の IBM Data Server Provider for .NET を使って、64 ビット Windows インスタンス上 で 32 ビット .NET アプリケーションを実行できます。64 ビットのコンピューターで 32 ビット版の IBM Data Server Provider for .NET を使うには、IBM Data Server Driver Package の 32 ビット 版をインストールします。 注: IBM Data Server Provider for .NET を使った迅速なアプリケーション開発の詳細については、 228 DB2 アプリケーション開発入門 IBM Information Management and Visual Studio .NET ゾーンを参照してください。 http://www.ibm.com/developerworks/data/zones/vstudio/index.html. .NET アプリケーションの開発に Visual Studio も使えます。6.3.1 節では IBM Database AddIns for Visual Studio について学習します。 6.3.1 IBM Database Add-Ins for Visual Studio IBM Database Add-Ins for Visual Studio は Visual Studio 開発環境とシームレスに統合されて おり、DB2 サーバーと協調して DB2 のプロシージャー、ユーザー定義関数やオブジェクトを開発 するための機能群を提供します。 IBM Database Add-Ins for Visual Studio は DB2 データベースに対するシンプルなインターフェ ースを提供するようにデザインされています。たとえば、SQL を使わずにデザイナやウィザードで データベース・オブジェクトを作成できます。また、SQL を使う必要がある場面では、統合された DB2 SQL エディターが以下の機能を提供します。 可読性向上のために色づけされた SQL 文 Misrosoft Visual Studio IntelliSense との統合により、DB2 スクリプトの作成中にインテリ ジェントなオート・コンプリート機能が提供されます。 IBM Database Add-Ins for Visual Studio は以下の機能を提供します。 オープンで様々な DB” 開発および管理ツール Solution Explorer による DB2 プロジェクトの作成と管理 DB2 データ接続の接続と管理 (Visual Studio 2005 以降では Server Explorer から実行 できます。) DB2 スクリプトの作成と変更。ストアード・プロシージャー、ユーザー定義関数、表、ビュー、 索引やトリガーを作成するスクリプトを含みます。 注: 本稿執筆時点で IBM Database Add-Ins for Visual Studio は Visual Studio 2010 をサポートし ていません。2010 9 月から開始されているベータテストについては、.NET Development with DB2 and IDS フォーラムを参照してください。 http://www.ibm.com/developerworks/forums/thread.jspa?messageID=14528477 6.3.1.1 IBM Database Add-ins for Visual Studio のインストール BM Database Add-ins for Visual Studio は独立してインストール可能なコンポーネントであり、 http://www.ibm.com/db2/express/download.html からダウンロードできます。DB2 製品をインス トール後、db2exc_vsai_xxx_WIN_x86.exe 実行ファイルをダブルクリックして IBM Database Add-Ins for Visual Studio をインストールできます。ここで xxx は DB2 サーバーと一致するバー ジョン番号です。このアドインのインストールは簡単で、すべてデフォルトを受け入れるだけです。 第 6 章 – .NET によるアプリケーション開発 229 図 6.4、6.5 および 6.6 は IBM Database Add-Ins for Visual Studio をインストールするときに表 示されるいくつかの画面を例示しています。 図 6.4 - IBM Database Add-Ins for Visual Studio のインストール – ようこそ画面 230 DB2 アプリケーション開発入門 図 6.5 - IBM Database Add-Ins for Visual Studio のインストール – インストール・フォルダの 選択 図 6.6 - IBM Database Add-Ins for Visual Studio のインストール – セットアップ完了 もしコンピューターに Visual Studio がインストールされれていない場合、アドインはインストールさ れません。 注: IBM Database Add-Ins for Visual Studio の使用方法の詳細については、IBM Information Management and Visual Studio zone を参照してください。 http://www.ibm.com/developerworks/data/zones/vstudio/index.html. 6.3.2 DB2 と Visual Studio の使用 この章では Visual C# ADO.NET アプリケーションを作成する手順を説明します。Visual Basic、 Visual J#、Visual C/C# などでもほぼ同様の手順が使えます。 6.3.2.1 Visual C# ADO.NET アプリケーションの作成 以下の手順で Visual Studio を使って Visual C# ADO.NET アプリケーションを作成します。 1. Visual C# プロジェクトを作成します。 ファイル -> 新規プロジェクトを選択します。 第 6 章 – .NET によるアプリケーション開発 231 新しいプロジェクトダイアログでプロジェクトの種類として Visual C# フォルダーを選択し、 テンプレートから Windows Forms アプリケーションを選択します。プロジェクト名と場所を それぞれ指定します。 図 6.7 – 新規 Visual C# .NET の作成 2. IBM Database Add-ins for Visual Studio がインストールされると、図 6.8 にようにソリューショ ン エクスプローラーへデータソースタブが追加されます。 図 6.8 – データソースタブの追加 232 DB2 アプリケーション開発入門 3. data adapter を Windows フォームにドラッグ&ドロップし、data grid コントロールも同様に ドラッグ&ドロップします。必要に応じて名前を変更します。 4. db2DataAdapter を右クリックし、データ・セットの生成を選択します。新規の DataSet1 を 選択して OK をクリックします。これによってデータ・セットと db2Dataset1 という名前のオ ブジェクトインスタンスが作成されます。 5.フォーム上の dataGrid_employee をクリックし、EMPLOYEE 表とデータグリッドのデータ バインドを行うために以下のプロパティーを指定します。 DataSource : Db2DataSet111 を選択します。 DataMember: EMPLOYEE を選択します。 図 6.9 – データ ソースの選択 6.図 6.10 のように GUI ツールを使って接続文字列を生成します。 第 6 章 – .NET によるアプリケーション開発 233 図 6.10 – 接続文字列の生成 接続文字列は実行時に以下のように生成されます。 DB2Connection con = new DB2Connection("Database=sample;User ID=db2admin;Server=localhost:50000;Persist Security Info=True;Password=db2admin"); DB2DataAdapter da = new DB2DataAdapter("select * from administrator.Employees",con); DataSet db2DataSet11 = new DataSet(); da.Fill(db2DataSet11); GridView1.DataSource =db2DataSet11; GridView1.DataBind(); 7.データ・ソースの生成が成功すると、図 6.11 のようにデータ・メンバーがデータソースタブにリスト されます。 234 DB2 アプリケーション開発入門 図 6.11 – データ ソースタブでのデータ メンバーの一覧 8. form.cs をダブルクリックしてコードウィンドウを開き、図 6.12 に示す小さなプログラムを記述しま す。 第 6 章 – .NET によるアプリケーション開発 235 図 6.12 – form.cs 内のコード記述 9.サンプル・プログラムをテストするには、Visual Studio のメニューからデバッグ-> デバッグ開始を クリックしてビルドと実行を行います。すべて期待通り動作すれば、図 6.13 のように DB2 の SAMPLE データベースから取り出されたデータがグリッドに表示されます。 図 6.13 - グリッドに表示された値 6.4 .NET による DB2 アプリケーションの開発 この節では、どのように DB2 データベースへの接続を確立して情報を取り出すかについて説明し ます。これまでに説明したそれぞれのドライバーを使い、データベース SAMPLE にユーザー db2admin、パスワード mypsw で接続する例を示します。このサンプル・コードは本書と共に提供 される Exercise_Files_DB2_Application_Development.zip に含まれています。 236 DB2 アプリケーション開発入門 Step 1: データベース接続の構成 eBook Getting started with DB2 Express-C - 3rd Edition. の DB2 Client Connectivity 章で記 述されているように DB2 データベースへの接続をセットアップします Step 2: 参照の追加 参照を追加するためにメニューバーから表示 -> ソリューション エクスプローラー を選択します。プ ロジェクトを右クリックして参照の追加を選択します。参照の追加ダイアログで使用したいデータ・プ ロバイダーを選択します。 図 6.14 – データ・プロバイダーの参照の追加 Step 3: プログラムのコンパイル プログラムをコンパイルするには、図 6.15 のようにメニューバーから ビルド -> ソリューションのビル ド を選択します。 第 6 章 – .NET によるアプリケーション開発 237 図 6.15 – プログラムのコンパイル Step 4: プログラムの実行 プログラムを実行するには、図 6.16 のようにメニューバーから デバッグ -> デバッグ開始 を選択し ます。 図 6.16 – プログラムの実行 6.4.1 IBM Data Server Provider for .NET による DB2 データベース接続 リスト 6.4 は Visual Basic でデータベースへ接続し、簡単な照会を実行する方法を示しています。 (1) Imports IBM.Data.DB2 Module Module1 Sub Main() Dim cmd As DB2Command Dim con As DB2Connection Dim rdr As DB2DataReader Dim v_IBMREQD As String Try con = New DB2Connection("Database=sample;" + "UID=db2admin;PWD=mypsw;") cmd = New DB2Command() (2) cmd.Connection = con (3) cmd.CommandText = "SELECT * FROM SYSIBM.SYSDUMMY1" 238 DB2 アプリケーション開発入門 cmd.CommandTimeout = 20 con.Open() (4) rdr = cmd.ExecuteReader(CommandBehavior.SingleResult) v_IBMREQD = "" While (rdr.Read() = True) v_IBMREQD = rdr.GetString(0) End While Dim strMsg As String strMsg = "Successful retrieval of record. Column " + "'IBMREQD’ has a value of '" + v_IBMREQD + "'" Console.WriteLine(strMsg) Console.ReadLine() (5) rdr.Close() (6) con.Close() Catch myException As DB2Exception End Try End Sub End Module リスト 6.4 – Visual Basic ADO.NET コード例 (IBM Data Server Provider for .NET) リスト 6.4 の各項目を見ていきましょう。 11. このステートメントは IBM.Data.DB2 をインポートしています。これは IBM Data Server Provider for .NET を使うことを示しています。 12. cmd.Connection に接続オブジェクトを割り当てます、これでデータベースに照会を実 行できます。 13. cmd.CommandText にデータベースで実行される照会を設定します。 14. cmd.ExecuteReader によってコマンドが実行され、DataReader オブジェクトの rdr がインスタンス化されます。 15. DataReader オブジェクトをクローズします。 16. Connection オブジェクトをクローズします。 リスト 6.5 は C# でデータベースへ接続し、簡単な照会を実行する方法を示しています。 using System; using System.Collections.Generic; using System.Text; using IBM.Data.DB2; namespace c1 { class Program 第 6 章 – .NET によるアプリケーション開発 239 { static void Main(string[] args) { DB2Command cmd = null; DB2Connection con = null; DB2DataReader rdr = null; string v_IBMREQD; int rowCount; try{ con = new DB2Connection("Database=sample;UID=db2admin;PWD=mypsw;"); cmd = new DB2Command(); cmd.Connection = con; cmd.CommandText = "SELECT * FROM SYSIBM.SYSDUMMY1"; cmd.CommandTimeout = 20; con.Open(); rdr = cmd.ExecuteReader(System.Data.CommandBehavior.SingleResult); v_IBMREQD = ""; while (rdr.Read() == true) { v_IBMREQD = rdr.GetString(0); } string strMsg; strMsg = " Successful retrieval of record. Column" + " 'IBMREQD' has a value of '" + v_IBMREQD + "'"; Console.WriteLine(strMsg); Console.Read(); rdr.Close(); con.Close(); } catch (DB2Exception myException) { } } private static void getch() { throw new Exception("The method or operation is not implemented."); } } } リスト 6.5 – C# ADO.NET コード例 (IBM Data Server .NET Data Provider) 6.4.2 OLE DB .NET Data Provider による DB2 データベース接続 リスト 6.6 は Visual Basic で OLE DB .NET Data Provider を使ってデータベースへ接続し、簡 単な照会を実行する方法を示しています。 Imports System.Data.OleDb 240 DB2 アプリケーション開発入門 Module Module1 Sub Main() Dim cmd As OleDbCommand Dim con As OleDbConnection Dim rdr As OleDbDataReader Dim v_IBMREQD As String Try con = New OleDbConnection("DSN=sample;UID=db2admin;PWD=mypsw;" "Provider='IBMDADB2';") cmd = New OleDbCommand() cmd.Connection = con cmd.CommandText = "SELECT * FROM SYSIBM.SYSDUMMY1" cmd.CommandTimeout = 20 con.Open() rdr = cmd.ExecuteReader(CommandBehavior.SingleResult) While rdr.Read() v_IBMREQD = rdr.GetString(0) End While Dim str1 As String str1 = "'IBMREQD' has a value of '" + v_IBMREQD + "'" 'Console.WriteLine('IBMREQD' has a value of '" + v_IBMREQD + "'") Console.WriteLine(str1) Console.ReadLine() rdr.Close() con.Close() Catch myException As OleDbException End Try End Sub End Module + リスト 6.1 – Visual Basic ADO.NET コード例 (OLE DB .NET Data Provider) リスト 6.7 は C# で OLE DB .NET Data Provider を使ってデータベースへ接続し、簡単な照会を 実行する方法を示しています。 using System; using System.Collections.Generic; using System.Text; using System.Data.OleDb; namespace c2 { class Program { 第 6 章 – .NET によるアプリケーション開発 241 static void Main(string[] args) { OleDbCommand cmd = null; OleDbConnection con = null; OleDbDataReader rdr = null; int rowCount; string v_IBMREQD, strMsg; try { con = new OleDbConnection("DSN=sample;UID=db2admin;PWD=mypsw;" "Provider='IBMDADB2';"); cmd = new OleDbCommand(); cmd.Connection = con; cmd.CommandText = "SELECT * FROM SYSIBM.SYSDUMMY1"; cmd.CommandTimeout = 20; con.Open(); rdr = cmd.ExecuteReader(System.Data.CommandBehavior.SingleResult); v_IBMREQD = ""; while (rdr.Read() == true) { v_IBMREQD = rdr.GetString(0); } strMsg = " Successful retrieval of record. Column" + " 'IBMREQD' has a value of '" + v_IBMREQD + "'"; Console.WriteLine(strMsg); Console.ReadLine(); rdr.Close(); con.Close(); } catch (OleDbException myException) { } } } } + リスト 6.7 – C# ADO.NET コード例 (OLE DB .NET Data Provider) 6.4.3 ODBC .NET Data Provider による DB2 データベース接続 リスト 6.8 は Visual Basic で ODBC .NET Data Provider を使ってデータベースへ接続し、簡単 な照会を実行する方法を示しています。 Imports System.Data.Odbc Module Module1 Sub Main() Dim cmd As OdbcCommand Dim con As OdbcConnection Dim rdr As OdbcDataReader 242 DB2 アプリケーション開発入門 Dim v_IBMREQD As String Try con = New OdbcConnection("DSN=sample;UID=db2admin;PWD=mypsw;" + DB2 ODBC DRIVER};") cmd = New OdbcCommand() cmd.Connection = con cmd.CommandText = "SELECT * FROM SYSIBM.SYSDUMMY1" cmd.CommandTimeout = 20 con.Open() "Driver={IBM rdr = cmd.ExecuteReader(CommandBehavior.SingleResult) While rdr.Read() v_IBMREQD = rdr.GetString(0) End While Dim str1 As String str1 = "'IBMREQD' has a value of '" + v_IBMREQD + "'" Console.WriteLine(str1) Console.ReadLine() rdr.Close() con.Close() Catch myException As OdbcException End Try End Sub End Module リスト 6.8 – Visual Basic ADO.NET コード例 (ODBC .NET Data Provider) リスト 6.9 は C# で ODBC .NET Data Provider を使ってデータベースへ接続し、簡単な照会を 実行する方法を示しています。 using System; using System.Collections.Generic; using System.Text; using System.Data.Odbc; namespace c3 { class Program { static void Main(string[] args) { OdbcCommand cmd = null; OdbcConnection con = null; OdbcDataReader rdr = null; string v_IBMREQD, strMsg; 第 6 章 – .NET によるアプリケーション開発 243 try { con = new OdbcConnection("DSN=sample;UID=db2admin;PWD=mypsw;" + "Driver={IBM DB2 ODBC DRIVER};"); cmd = new OdbcCommand(); cmd.Connection = con; cmd.CommandText = "SELECT * FROM SYSIBM.SYSDUMMY1"; cmd.CommandTimeout = 20; con.Open(); rdr = cmd.ExecuteReader(System.Data.CommandBehavior.SingleResult); v_IBMREQD = ""; while (rdr.Read() == true) { v_IBMREQD = rdr.GetString(0); } strMsg = " Successful retrieval of record. Column" + " 'IBMREQD' has a value of '" + v_IBMREQD + "'"; Console.WriteLine(strMsg); Console.ReadLine(); rdr.Close(); con.Close(); } catch (OdbcException myException) { } } } } リスト 6.9 – C# ADO.NET コード例 (ODBC .NET Data Provider) ODBC .NET Data Provid 使用時のみ、先に記述した Step 1 に追加の手順が必要です。 Step 1: 接続の構成 DB2 データベースは ODBC データ・ソースとしてカタログされている必要があります。 ODBC データ・ソースとしてカタログするには以下の手順を実行します。 db2 catalog system ODBC data source <databasename> もしくは db2 catalog user ODBC data source <databasename> ODBC データ・ソースをリストするには以下のコマンドを実行します。 db2 list system ODBC data sources もしくは db2 list user ODBC data sources コンパイルと実行の手順に変更はありません。 244 DB2 アプリケーション開発入門 6.5 .NET を使ったデータの操作 以 下 の C# サ ン プ ル ・ コ ー ド は 、 IBM Data Server Provider for .NET に 含 ま れ る ク ラ ス DB2Connection, DB2Command, and DB2Transaction を使った SELECT、INSERT、 UPDATE および DELETE の方法を示しています。 リスト 6.10 は SELECT を実行する方法を示します。 (1) cmd.CommandText = "SELECT deptnumb, location " + " FROM org " + " WHERE deptnumb < 25"; (2) DB2DataReader reader = cmd.ExecuteReader(); リスト 6.10 – SELECT の C# コード例 リスト 6.10 の各項目を見ていきましょう。 (1) cmd.CommandText は確立済みの接続を使って実行される照会を指定します。 (2) reader は DataReader オブジェクトのインスタンスであり、cmd.ExecuteReader メソッドを 使ってコマンドを実行します。ExecuteReader メソッドは CommandText を Connection に 送り、DB2DataReader を生成します。 リスト 6.11 は INSERT を実行する方法を示します。 // Use the INSERT statement to insert data into the 'staff' table. cmd.CommandText = "INSERT INTO staff(id, name, dept, job, salary) " + " VALUES(380, 'Pearce', 38, 'Clerk', 13217.50),” + " (390, 'Hachey', 38, 'Mgr', 21270.00), " + " (400, 'Wagland', 38, 'Clerk', 14575.00)”; (1) cmd.ExecuteNonQuery(); リスト 6.11 - INSERT の C# コード例 リスト 6.11 の項目をみていきましょう。 (1) cmd.ExecuteNonQuery は Connection に対して SQL ステートメントを実行し、影響を 受けた行数を返します。 リスト 6.12 は UPDATE を実行する方法を示します。 // This method demonstrates how to update rows in a table cmd.CommandText = "UPDATE staff " + " SET salary = (SELECT MIN(salary) " + " FROM staff " + " WHERE id >= 310) " + " WHERE id = 310"; cmd.ExecuteNonQuery(); リスト 6.12 – UPDATE の C# コード例 第 6 章 – .NET によるアプリケーション開発 245 リスト 6.13 は DELETE を実行する方法を示します。 // This method demonstrates how to delete rows from a table { try cmd.CommandText = "DELETE FROM staff " + " WHERE id >= 310 " + " AND salary > 20000"; cmd.ExecuteNonQuery(); リスト 6.13 – DELETE の C# コード例 6.5.1 サンプル・プログラムのビルドと実行 ここに示したコード例は DB2 と共に出荷されるサンプル・プログラム TbUse.cs から抜粋したもの です。このファイルは以下のディレクトリーにあります。 C:\Program Files\IBM\SQLLIB\samples\.NET\cs これらのプログラムを実行するには、以下の手順を実行します。 1. DB2 コマンド・ウィンドウで bldapp.bat を使って TbUse.cs をコンパイルします。 bldapp TbUse もしくは、コマンド・プロンプトで makefile を使って TbUse.cs をコンパイルします。 nmake TbUse 2. TbUse プログラムを実行するには、コマンド・プロンプトからプログラム名を入力します。 TbUse 注: サンプル・プログラムについての詳細は、以下のページを参照してください。 http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.sam ptop.doc/doc/c0007609.html 6.6 演習 以下の手順に従って、SAMPLE データベースにある BLOB データをアクセスする C# プログラム を書きなさい。 246 DB2 アプリケーション開発入門 1. まだ SAMPLE データベースを作成していない場合、DB2 コマンド・ウィンドウから以下のコ マンドを実行してデータベースを作成します。 db2sampl 2. EMP_PHOTO と EMP_RESULE 表から BLOB および CLOB データの照会および更新を 行う C# プログラムを書きなさい。この課題が難しい場合、以下のリンクの “Retrieving and updating BLOBs and CLOBs” 章にある db2lobs.zip プロジェクトに含まれるサンプル・プロ グラムを参照しなさい。 http://www.ibm.com/developerworks/data/library/techarticle/0304surange/0304surang e.html#resources 3. 適切なスキーマ名に更新し、テストしなさい。 4. C# プログラムを実行するには、6.5.1 にリストされた手順に従いなさい。 6.7 まとめ この章では DB2 のための .NET アプリケーション開発環境のセットアップ方法を説明しました。ま た、様々なデータ・プロバイダーや、プロバイダー毎のコードの記述方法についても説明しました。 パフォーマンスが最も良いため、IBM Data Server data provider for .NET が推奨されるプロバイ ダーです。IBM Database Add-Ins for Visual Studio についても説明しました。この章では DB2 データベースへの接続方法や DB2 データの操作方法についても説明しました。 6.8 確認問題 1. DataReader オブジェクトの FieldCount と HasRows 公開プロパティーの違いは何です か? 2. ODBC .NET Data Provider を使うときだけ必要になる構成は何ですか? 3. ADO.NET によるデータ・アクセスが依存する 2 つのコンポーネントの名前と説明 4. 64 ビット・コンピュータで 32 ビット IBM Data Server Provider for .NET は使えますか? 5. Visual Studio Add-Ins と DB2 をどのように使いますか? 6. ADO.NET における非接続型のデータ・アクセスのキー・コンポーネントは? A. DataSet B. DataReader C. Connection D. DataAdapter E. 7. 上のいずれでもない データを持つ非接続型の DataSet を保持するコンポーネント・クラスは以下のどれですか? A. Command object 第 6 章 – .NET によるアプリケーション開発 247 B. DataReader object C. DataAdapter object D. Dataset E. 8. 上のいずれでもない SQL ステートメントもしくはストアード・プロシージャーのどちらを実行するかを指定するために 使われる Command オブジェクトの公開プロパティーはどれですか? A. CommandText B. CreateParameter C. ExecuteNonQuery D. CommandType E. 9. 上のいずれでもない 以下のすべての .NET データ・プロバイダーは、あるドライバーを除いて DB2 アプリケーショ ンがデータベース・アクセスに使えます。あるドライバーとは? A. IBM Data Server Provider for .NET B. Microsoft .NET Data Server Provider C. OLE DB .NET Data Provider D. ODBC .NET Data Provider E. 上のいずれでもない 10. IBM Database Add-Ins for Visual Studio で DB2 プロジェクトの作成に使われるものは? A. Object Browser B. Server Explorer C. Solution Explorer D. Device Emulator Manager E. 上のいずれでもない 7 第 7 章 Ruby on Rails によるアプリケーション開発 Ruby はオープン・ソースで無償の動的プログラミング言語です。単に Rails と呼ばれることもある Ruby on Rails (RoR) は Ruby で構築されたフレームワークです。RoR はモデル・ビュー・コント ローラー(MVC)アーキテクチャーにのっとっており、アジャイル開発手法をサポートした結果、 Web アプリケーションの開発者の時間と苦労を大幅に軽減することができます。 この章では以下の内容を学びます: Ruby on Rails と MVC アーキテクチャー DB2 と稼働させるための Ruby on Rails のセットアップ DB2 と稼働する RoR プログラムの基本的な考え方 DB2 と稼働する簡単な RoR アプリケーションの作成方法 7.1 DB2 と稼働する Ruby on Rails アプリケーション:概要 Ruby on Rails はモデル・ビュー・コントローラーアーキテクチャ(通常単に MVC と呼ばれます)に のっとって構築されています。MVC の利点は: 業務ロジックとユーザーインターフェースを分離できる 異なるタイプのコードが属する個所が明確になるのでメンテナンスが容易になる モデルはアプリケーションが処理する情報(データ)とデータの操作に関するルールを表していま す。Rails の場合、モデルはまず対応するデータベースの表とのやりとりのルールを管理するため に用いられます。ほとんどのケースでは、データベースのひとつの表がアプリケーションのひとつの モデルに対応します。アプリケーションの業務ロジックの大半はこのモデルの中に含まれます。 MVC では、DB2 は永続データを提供します。 コントローラーはモデルとビューの間の「接着剤」の役割を提供します。Rails では、コントローラー は Web ブラウザーからの要求を受け付け、データを表すモデルに問い合わせを行ない、結果を 表示のためビューに渡します。 ビューはアプリケーションのユーザー・インターフェースを担当します。Rails では、ビューは通常 Ruby コードを埋め込まれた HTML ファイルで、データの表示を行ないます。ビューは、アプリケ 250 DB2 アプリケーション開発入門 ーションからの要求を実行するためにデータを Web ブラウザーまたはその他のツールに提供する 処理を行ないます。 図 7.1 RoR - DB2 アプリケーション: MVC アーキテクチャー (1) ユーザーが http://localhost:3000/myapp1 を Web ブラウザーから入力 (2) コントローラーにルーティング (3) コントローラーがモデルと会話 (4) モデルが DB2 にアクセス (5) コントローラーがビューと会話 (6) ビューが表示するデータをブラウザーに渡す 図 7.1 RoR - DB2 アプリケーション: MVC アーキテクチャー 上図では、ユーザーが Web ブラウザーからアプリケーションの URL を入力することで、該当ア プリケーションが起動されます(1)。この例では、WEBrick と呼ばれる RoR の Web サーバーが同 じマシン(localhost)に導入されており、デフォルトではポート 3000 を listen しています。アプリケ ーションを起動するための URL は http://localhost:3000/myapp1 となります(myapp1 はコントロ ーラーの名前です)。 第 7 章 - Ruby on Rails によるアプリケーション開発 251 要求はルーティングモジュールによってコントローラーに渡され、処理が開始されます(2)。コント ローラーは要求を処理するためのモデルと会話し(3)、モデルは必要であれば DB2 にアクセスし て永続データを取得します(4)。モデルの返答をうけてコントローラーはビューと会話し(5)、最終的 にビューがブラウザーに表示すべき情報を提供します(6)。 RoR アプリケーションはオブジェクト指向アプリケーションです。DB2 を含む多くの商用データベ ースはリレーショナル・データベース・モデルを採用しており、この両者を結びつけるためにはオブ ジェクト・リレーショナル・マッピング(ORM)ライブラリーを用いるのが一般的です。アクティブ・レコ ードは Rails が提供する ORM レイヤーです。標準 ORM モデルに準拠し、表はクラスに、行はオ ブジェクトに、列はオブジェクト属性にそれぞれ対応します。 ORM を使うことで、データベース・スキーマの変更に対する対応が容易になります。例えば、表 の内容を他の情報と合わせて画面に表示するアプリケーションがあったとします。これに対し、顧 客が表にいくつか列を追加してそれらも表示するように要求してきました。これは一見簡単な要求 のように見えますが、実際には非常に手間のかかる作業でバグのリスクも潜んでいます。該当の表 を参照するすべての SQL を探して追加した列を含むように修正する必要があります。ORM では このような修正はずっと容易になります。データベースのエンティティーとプログラムのエンティティ ーのマッピング情報は XML 構成ファイルに保管されており、プログラマーはこの XML ファイルを 修正して列を追加すれば、ORM が XML ファイルの内容にのっとって適切な SQL を生成してく れます。またこれにより同一の SQL をアプリケーションの中の別々の個所でコーディングする必要 がなくなります。アクティブ・レコード(Rails の ORM)では、しかし、XML 構成ファイルも不要です。 Rails は次の二つの指針に基づいて設計されています: a) 同じことを繰り返さない ("Do not Repeat Yourself - DRY") b) 構成よりも規則優先 ("Convention Over Configuration - CoC") DRY は、システム中でひとつの内容は一個所でのみ表現されている、という考え方です。これによ り、プログラマーがアプリケーションの複数の個所を修正する必要がなくなります。 CoC では、プログラマーが規則に従うことで、一貫性を保ちつつも記述しなければならない量を減 らすことができます。表 7.1 では規則と例を示しています。 規則 例 表名はすべて小文字で、複数形 books モデルの名前はクラス名の命名規則に従い分 割されない大文字小文字をまじえた名前で、表 名の単数形。Ruby 言語ではクラス名の先頭文 字は大文字です。 Book コントローラークラス名は複数形 BooksController Rails はクラス定義を /app/models ディレクトリ ーの book.rb ファイルから検索します。 Rails はクラス定義を /app/controllers ディレク トリーの books_controller.rb ファイルから検索 します。 252 DB2 アプリケーション開発入門 表 7.1 CoC 指針の例 7.2 RoR 環境のセットアップ RoR アプリケーションを作成する前に、まず Ruby、Rails、DB2 ドライバーとアダプターを導入し、 ファイルを構成する必要があります。プラットフォームによって手順は異なります。 注: この本では、Windows 環境に RoR をセットアップすることを想定して解説しています。その他の 環境に RoR をセットアップする場合は、DB2 Campus フリーブックシリーズの Getting started with Ruby on Rails の該当個所を参照してください。 7.2.1 Ruby の導入 Ruby を Windows 環境に導入するには、http://rubyforge.org/frs/?group_id=167 から Oneclick Installer - Windows を使用してください。 この記事を執筆している時点での Ruby の最新バージョンは 1.8.6-27 Release Candidate 2 で す。ruby186-27_rc2.exe 実行ファイルを選択してクリックし、そのまま実行するかあるいはいった ん保存するかを選ぶことができます。ここでは Run を選択します。するといったん一時領域に保存 されたファイルが起動されます。 導入は非常に簡単です。ライセンスに同意し、導入ディレクトリーを選択して、以後の構成は省略 時値のままでかまわないのでそのまま Next ボタンを数回クリックします。Install をクリックすると導 入が開始され、図 7.2 から 7.4 のような画面が表示されます。 第 7 章 - Ruby on Rails によるアプリケーション開発 253 図 7.2 Ruby の導入・コンポーネントの選択 コンポーネントの選択画面では、enable RubyGems をチェックします。RubyGems については 後で説明します。 254 DB2 アプリケーション開発入門 図 7.3 Ruby の導入・導入ディレクトリーの選択 第 7 章 - Ruby on Rails によるアプリケーション開発 255 図 7.4 Ruby の導入・導入進捗バー Ruby の導入が完了したら、Next をクリックし、さらに Finish をクリックしてください。もし readme ファイルを確認したければ、Show Readme チェックボックスをチェックしてください。 ついで、Ruby が正常に導入されたことを確認するため、Ruby のバージョンを確認しておきましょ う。Windows コマンド・プロンプトから、-v フラグをつけて ruby コマンドを実行してください。図 7.5 は実行例です。 図 7.5 導入された Ruby のバージョンの確認 また、Windows のスタートボタンから Ruby メニューが登録されていることを確認してください(スタ ート -> プログラム -> Ruby-186-27)。 注: こ の 章 で は 、 <ruby_home> は Ruby が 導 入 さ れ た デ ィ レ ク ト リ ー を 意 味 し ま す 。 ま た 、 <app_home> は Rails 導入時に作成されたアプリケーションのホーム・ディレクトリーを意味しま す。 7.2.1.1 RubyGems:Ruby パッケージの保管場所、導入、更新 RubyGems は、Ruby ライブラリーとアプリケーションの標準パッケージであり、導入フレームワー クです。RubyGems によって、Ruby パッケージを簡単に見つけ、導入し、更新し、または除去す ることができます。 RubyGems の世界では、ひとつの gem は Ruby アプリケーションまたはライブラリーのパッケー ジを意味します。これらのファイルは、決まったフォーマットに従ってパッケージされ、インターネット 上のリポジトリーに保管されています。gem は例えば rake 0.4.16 のように名前とバージョンを持っ ています。 同じく gem と呼ばれるコマンドラインツールが、これらの gem ファイルの操作のために使用できま す。もし gem が必要なら、たんに RubyGems に対してその gem (と必要な前提)をオンラインか ら導入するよう命令するだけです。図 7.6 は "rake" gem がインターネットを通じて導入される仕組 みを表しています。 256 DB2 アプリケーション開発入門 図 7.6 rake gem の導入 この図に見られるように、Ruby が導入されているマシンから gem install rake コマンドを実行し ます。すると自動的に http://rubygems.org/ に接続して rake ライブラリーや rake コマンドライン・ プログラムを見つけ出します。rake コマンドについては後で解説します。いまは、rake は新たな gem を作成するのに使用できるコマンドであることを理解していただければ十分です。ライブラリ ーやコマンドライン・プログラムがダウンロードされると、これらは自動的に導入されます。 7.2.2 Rails の導入 RubyGems によって、その他の gem と同様に、Rails とその前提を簡単に導入することができま す: 1. コマンド・プロンプトを開きます。 スタート -> 全てのアプリケーション -> アクセサリー -> コマンドプロンプト 2. ディレクトリーを <ruby_home> に変更し、gem コマンドを実行します: gem install rails すべてのパッケージを導入するには、ネットワークスピードによっては数分かかることがあります。 gem コマンドは http://rybygems.org/ サイトにアクセスして要求された Rails パッケージを検索し ます。ダウンロードと導入が完了すると、図 7.7 のような画面が表示されます。 第 7 章 - Ruby on Rails によるアプリケーション開発 257 図 7.7 Rails の導入 Rails が正常に導入されたことを確認するために、rails コマンドを -v オプション付きで実行してく ださい。図 7.8 のように、Rails のバージョンが表示されます。 図 7.8 Rails のバージョン 7.2.3 RoR アプリケーションの作成と Web サーバーの起動 では RoR アプリケーションを作成してみましょう。非常に簡単で、コードを記述する必要はありませ ん!: 1. ディレクトリーを <ruby_home> に変更します: cd <ruby_home> 2. myapp1 という名前の RoR アプリケーションを作成します。 rails myapp1 図 7.9 の画面が表示され、アプリケーション myapp1 のための構造が作成されます。この時点 でまだあなたはまったくコードを記述していません。 258 DB2 アプリケーション開発入門 図 7.9 RoR アプリケーション myapp1 の作成 3. アプリケーション myapp1 と同じ名前のディレクトリーが作成されています。ディレクトリーを変更 します。 cd myapp1 4. WEBrick Web サーバーを起動します。 ruby script/server Web サーバーが起動すると、図 7.10 の画面が表示され、プロセス ID (PID) と TCP/IP のリスニ ングポート番号 (デフォルトの 3000) がわかります。 図 7.10 WEBrick Web サーバーの起動 Web サーバーが起動しました。ブラウザーを起動して、http://localhost:3000/ にアクセスしてみ ましょう。図 7.11 と同じ画面が表示されるはずです。 第 7 章 - Ruby on Rails によるアプリケーション開発 259 図 7.11 Welcome ページ ここまでの作業で、アプリケーション myapp1 を開発するために必要な構造が作成され、Web サ ーバーが起動しました。以降のセクションでは、DB2 データベースを利用してモデル、ビュー、コン トローラーを作成する方法について解説します。 7.2.4 DB2 データベースを使う:ibm_db gem DB2 の Rails サポートは、ibm_db と呼ばれる IBM から直接提供されるオープン・ソース gem で 提供されます。この gem は C で記述された Ruby が DB2 とやりとりするために必要なドライバー と、Ruby で記述されたアクティブ・レコードを通じて DB2 をアクセスするために必要なアダプター を含んでいます。 ibm_db アダプターは ibm_db ドライバーを通じて、IBM Driver for ODBC and CLI を経由して IBM データ・サーバーに接続します。すでに述べた通り、アクティブ・レコードは Rails で提供され る ORM レイヤーです。これは標準 ORM モデルにほぼ準拠していますが、多くの ORM ライブラ リーと比べて構成方法が異なります。アクティブ・レコードは、厳密なデフォルトの集合を使用するこ とで、開発者が考慮しなくてはいけない構成の手間を最小化します。図 7.12 はアクティブ・レコー ドが ibm_db および DB2 サーバーとやりとりする流れを図式化したものです。 260 DB2 アプリケーション開発入門 図 7.12 Acrive Record と IBM_DB とのやりとり ibm_gem を導入すると、Rails は DB2 Express-C やその他のエディションの DB2 for Linux, UNIX, Windows、DB2 for i5/OS®、さらに DB2 for z/OS を利用できるようになります。 7.2.4.1 ibm_db gem の導入 ibm_db gem を Windows に導入する場合は、単に以下のコマンドを実行してください: gem install ibm_db このコマンドによって、すでに作成済みのバイナリーバージョンのドライバーを取得しますので、コ ンパイラーなどの開発ツールは不要です。もしリストからバージョンを選択するよう求められた場合 は、mwsin32 の中の最新のバージョンを選択してください。図 7.13 はその結果の画面表示です。 図 7.13 ibm_db gem の導入 Linux や UNIX の場合は、gem をソースから作成する必要がありますので、手順はやや複雑にな ります: 1. シェルを root ユーザーで起動します: $ sudo -s 2. 環境変数を設定します。ここでは DB2 インスタンスオーナーとして db2inst1 を想定していま す: $ export IBM_DB_INCLUDE=/home/db2inst1/sqllib/include $ export IBM_DB_LIB=/home/db2inst1/sqllib/lib 第 7 章 - Ruby on Rails によるアプリケーション開発 261 3. DB2 プロファイルを実行します。これは純粋にドライバーの作成だけを考えると必ずしも実行す る必要はありませんが、root ユーザーで db2 や db2level などのコマンドを実行できるようにな ります。 $ . /home/db2inst1/sqllib/db2profile 4. 同一シェル上から、ibm_db gem の導入を実行します: $ gem install ibm_db 5. gem が正常に導入されたら、exit を実行して root ユーザーのシェルを終了しましょう。 Mac OS X 10.6 Snow Leopard の場合は、以下の手順になります(Max OS X Tiger むけの DB2 はありません): 1. $ sudo -s 2. $ export IBM_DB_INCLUDE=/Users/myuser/sqllib/include 3. $ export IBM_DB_LIB=/Users/myuser/sqllib/lib64 4. $ export ARCHFLAGS="-arch x86_64" 5. $ gem update --system 6. $ gem install ibm_db 7. $ exit 7.2.4.2 database.yml 構成ファイル Ruby on Rails が正常に導入され、新しい Rails アプリケーションが作成されると、database.yml 構成ファイルが自動的に C:\<ruby_home>\<app_home>\confg ディレクトリーに作成されます。 先の例の通り、myapp1 アプリケーションを作成したとすると、C:\Ryby\myapp1\config となります。 database.yml ファイルは、アプリケーションが DB2 利用するために必要な情報を提供します。図 7.14 は SciTE エディターで開いたサンプルの database.yml ファイルです。SciTE エディターは Ruby とともに導入されています(スタート -> 全てのアプリケーション -> Ruby-186-27 -> SciTE)。 262 DB2 アプリケーション開発入門 図 7.14 構成ファイル database.yml の内容 図 7.14 を見ておわかりの通り、database.yml ファイルは三つの異なるセクション(development、 test 、 production ) を 含 ん で い ま す 。 こ れ ら は Rails が デ フ ォ ル ト で 実 行 で き る も の で す 。 development 環境は、アプリケーションを対話式に実行します。test 環境は、自動実行テストのた めに用いられます。production 環境は、アプリケーションを公開する場合に用いられます。 表 7.2 は、database.yml ファイルに含まれる属性の一部の説明です。 接続属性 説明 必須属性 Adapter Ruby アダプター名、DB2 の場合は ibm_db Yes Database Rails プロジェクトが接続するデータベ ースの別名または実名 Yes Username DB2 データベースに接続する際に用 いられるユーザー ID Yes 第 7 章 - Ruby on Rails によるアプリケーション開発 263 Password Username で指定されたユーザー ID のパスワード Yes Schema 名前付きオブジェクトの集まり。スキー マは、データベースに含まれるオブジ ェクトの論理的なグループを表します。 オプション。スキーマが省略された場合 は、現在のセッションユーザーの認証 ID がスキーマとして設定されます。 Application アプリケーション名。DB2 Connect を 通じて DB2 for i5/OS または DB2 for z/OS に接続する場合にのみ有効。 Optional クライアント・アカウント文字列。DB2 Connect を通じて DB2 for i5/OS ま たは DB2 for z/OS に接続する場合 にのみ有効。 Optional クライアント・ワークステーション名。 DB2 Connect を 通 じ て DB2 for i5/OS または DB2 for z/OS に接続す る場合にのみ有効。 Optional Host データベースが存在するリモートサー バーのホスト名。 リモート TCP/IP 接続に関する Host および Port 属性は、DB2 のカタログ 情報が無く、DB2 CLI の構成ファイル db2cli.ini にもデータソースが登録され ていない場合にのみ必要になります。 この形式の設定は、完全な DB2 クライ アントを導入する代わりに、IBM Driver for ODBC and CLI を導入している場 合に可能です。 Port DB2 インスタンスの TCP/IP ポート 上の Host 属性の説明を参照してくだ さい。 Account Workstation オプション オプション オプション 表 7.2 database.yml ファイルに構成する DB2 接続属性 7.3 RoR アプリケーションの開発 このセクションでは、Rails scaffolding を使って簡単な Web アプリケーションを開発する方法を 説明します。scaffold ユーティリティーを使えば、アプリケーションの主要部分を素早く生成するこ とができます。scaffold ユーティリティーは、一度の実行で新しいリソースのためのモデル、ビュー、 コントローラーを生成します。 264 DB2 アプリケーション開発入門 では scaffold ユーティリティーを使って簡単な Web アプリケーションを作成する方法を順に説明 していきましょう。このアプリケーションは DB2 を利用するものですから、最初に DB2 データベー スを作成して database.yml ファイルを構成する必要があります。 7.3.1 サンプルアプリケーションの開発:書籍カタログ bookapp と名付けられたこれから作成する書籍カタログ・アプリケーションは、ユーザーに書籍に 関する情報を提供するアプリケーションです。ここでは、一般ユーザーと作者という2種類のユーザ ーを想定します。bookapp アプリケーションの要件はシンプルです: 1. 一般ユーザーは書籍に関する情報を参照することができる 2. 作者は、一般ユーザーと同じく書籍情報を参照することができるが、それに加えて新しい 書籍をカタログに追加したり、既存の書籍情報を更新したりすることができる 3. 書籍情報を参照するために 1 ページ、書籍情報を更新するために 1 ページ用意する 4. 書籍情報を保存するために XML を使用する このアプリケーションで必要な表はひとつだけです。books 表の構造を図 7.3 に示します。 列名 データ型 説明 TITLE Varchar 書籍の名称 DESCRIPTION XML 書籍情報。著者名と簡単な説明を含む。 STATUS Varchar 書籍が注文可能か、完売か、未発売か、などの状 況を示す 表 7.3 books 表の列とその説明 DB2 サーバー上の表の作成は、 scaffold と rake コマンドによって RoR を通じて自動的に行わ れます。RoR は、アプリケーションが使用する列に加えて、いくつか追加の列を作成します。例え ば、プライマリーキーとして使用される ID 列です。 要件 3 で必要とされた 2 つのページは、それぞれが book と catalog というリソースに対応しま す。これらば scaffold コマンドを用いてあとで作成します。 今回の例では、RoR アプリケーション、WebBrick サーバー、および DB2 サーバーは全て同一の Windows マシン上で稼働します。このため、database.yml ファイルを構成する際に、今回は localhost を指定します。 7.3.1.1 DB2 データベースの作成 で は DB2 コ マ ン ド を 使 っ て booksdb デ ー タ ベ ー ス を 作 成 し ま し ょ う 。 Windows, ま た は Linux/UNIX 環境では: db2 create db booksdb using codeset utf-8 territory us 第 7 章 - Ruby on Rails によるアプリケーション開発 265 DB2 が内部オブジェクトを作成し、さらに自動構成を実行するのに数分かかることがあります。す でに述べた通り、DB2 ツールを使って books 表を作成する必要はありません。表の作成は RoR を通して自動的に行われます。 7.3.1.2 アプリケーション構造の作成 bookapp アプリケーションを作成するために、ターミナルを開いてファイル作成権限を持つフォル ダー(以後、このフォルダーを <app_home> と表記します)に移動し、以下のコマンドを実行して ください: rails –d ibm_db bookapp bookapp アプリケーションが作成されます。-d ibm_db は、DB2 データベースを使用するための ibm_db アダプターを組み込むことを意味します。図 7.16 は実行例です。 図 7.16 bookapp アプリケーションの作成 bookapp アプリケーションを作成すると、アプリケーションと同じ名前のフォルダーが作業ディレクト リーの下に作成されます。このフォルダーに移動しましょう。bookapp の場合の例です: cd <app_home>\bookapp 266 DB2 アプリケーション開発入門 You will note several directories and files were automatically created under that directory. このディレクトリーの下にいくつかのサブ・ディレクトリーやファイルが作成されていることに注意して ください。 表 7.4 は作成される主なサブ・ディレクトリーについて説明しています。 ディレクトリー 説明 app\ アプリケーションのためのモデル、ビュー、コントローラー、ヘルパーを保 存します config\ アプリケーションのランタイムルール、ルート、データベースなどの構成を 保管するファイルやサブ・ディレクトリーが含まれます db\ 現在のデータベース・スキーマや、データベースの移行に関するファイル やサブ・ディレクトリーが含まれます 表 7.4 RoR アプリケーションのデフォルトのディレクトリー構造 すでに述べた通り、database.yml を構成して、RoR アプリケーションに DB2 データベースに対し て ど の よ う に 接 続 す る か を 教 え て あ げ る 必 要 が あ り ま す 。 <app_home>\bookapp\config\database.yml ファイルの development セクションを以下のように 編集してください: development: adapter: ibm_db username: arfchong password: passwd database: booksdb host: localhost port: 50000 bookapp アプリケーションでは、ibm_db アダプターを使って booksdb データベースに接続しま す。今回、データベース・サーバーは RoR アプリケーションと同一のマシンにありますので、host と port 情報は必須ではありません。これらの情報を削除すると、RoR は DB2 データベースにロー カル接続を確立します。例では、host として localhost を、port として 50000 を指定しています。 この場合は、RoR は DB2 サーバーがリモートマシンに存在するときと同じように、TCPIP を使って 接続を確立します。 ユーザー ID とパスワードはリモートサーバーに接続する場合には指定するべきです。この例では username として arfchong、パスワードとして passwd を指定しています。それぞれ、適切な値に 置き換えてください。 ここでは、アプリケーションを development として稼働させますので、database.yml ファイルの test セクションと production セクションは削除、もしくはコメント・アウトしてかまいません。 第 7 章 - Ruby on Rails によるアプリケーション開発 267 構成が済んで、データベースに接続できるかどうか確認するためには、以下のコマンドを実行して ください: <app_home>\bookapp> rake db:migrate If you get an error, there is something wrong with the configuration values in database.yml, or maybe the DB2 instance is not running. An error means that Rails can’t work with your database. エラーが起きた場合は、database.yml ファイルが正しく構成されていないか、あるいは DB2 イン スタンスが起動していない可能性があります。 続いて、scaffolding を使ってアプリケーションのテンプレートを生成します。作成されたテンプレー トは、必要に応じてあとで更新することができます。以下の scaffold コマンドを実行して、TITLE、 DESCRIPTION、STATUS 列を持つ表からなる book リソースを作成します。 ruby <app_home>\bookapp\script\generate scaffold Book title:string description:xml status:string 図 7.17 は上記コマンドの実行結果です。 図 7.17 scaffold コマンドを使用した bookapp サンプル・アプリケーションの作成例 scaffold は様々な作業を行い、時間や手間をはぶいてくれます。もっとも注意すべきなのは 図 7.17 で赤く示したふたつです。ひとつはモデルそのものである book.rb で、もうひとつは移行ファ イル 20100611202808_create_books.rb です。 268 DB2 アプリケーション開発入門 移行ファイル 20100611202808_create_books.rb を見てみましょう。ファイル名にはタイムスタン プが含まれています。rb 拡張子は Ruby ファイルであることを示します。図 7.18 はこのファイルの 内容です。 図 7.18 移行ファイル 20100611202808_create_books.rb の内容 up メソッドは移行を DB2 に適用する際に用いられます。ここでは、表がどのように作成されたかを 示しています。down メソッドは up を取り消します。以前の状態に戻したい場合に実行されます。 rake db:migrate を実行して、database.yml ファイルを使ってデータベースに正しく接続できる かどうかをテストしましたが、このコマンドは単にデータベースに接続するだけでなく、移行ファイル を 参 照 し て 必 要 な 変 更 の 適 用 も 行 い ま す 。 scaffold ユ ー テ ィ リ テ ィ ー で 移 行 フ ァ イ ル 20100611202808_create_books.rb が作成されましたから、rake を実行すると移行ファイルの内 容でまだ適用されていないものが適用されます。このケースでは、books 表はまだ作成されていな いため、DB2 サーバー上に表を作成します。 rake コマンド の db:migrate パラメーターは、必要なコマンドや SQL を生成して DB2 に実行さ せることを意味します。図 7.19 は実行結果です。 図 7.19 rake db:migrate コマンドの実行 第 7 章 - Ruby on Rails によるアプリケーション開発 269 DB2 コマンド・ウィンドウまたは Linux/UNIX シェルから DB2 コマンドの list tables を実行して、 表が作成されていることを確認しましょう。図 7.20 は実行例です。 図 7.20 rake db:migrate コマンドで作成された DB2 の表の表示例 Figure 7.20 shows that rake db:migrate command created the BOOKS table, but also a table called SCHEMA_MIGRATIONS. This second table is used by RoR to track migration instructions for your database. 図 7.20 の実行結果を見ると、rake db:migrate コマンドによって BOOKS 表が作成されているこ とがわかります。しかし、それに加えて SCHEMA_MIGRATIONS という表が見えます。この表は、 RoR がデータベースの移行状況を追跡するために用いられます。 DB2 コマンド describe tables を使って、BOOKS 表の構造を確認します。図 7.21 が実行結果 です。 図 7.21 rake db:migrate コマンドで作成された BOOKS 表の構造 図 7.21 に見られるように、3つの新しい列 ID、CREATED_AT、UPDATED_AT が追加されてい ることに注意してください。Rails は、ID 列を主キーとして自動的に作成します。そのため、Rails で使用する表では明示的に主キーを指定することはできません。CREATED_AT、UPDATE_AT 列については、Rails はさまざまな場面でこれらの列を使用しますが、移行についてはこれらの列 は使用しません。移行に関する情報は移行テーブルに保管されます。 270 DB2 アプリケーション開発入門 同 時 に 作 成 さ れ た SCHEMA_MIGRATION 表 に つ い て も 見 て み ま し ょ う 。 図 7.22 は SCHEMA_MIGRATION 表の内容を表示したものです。 表 7.22 SCHEMA_MIGRATION 表の内容 図からわかるとおり、SCHEMA_MIGRATION 表は VERSION 列ひとつだけを含みます。この列 は移行のためのバージョン番号を保持しています。バージョンは、移行ファイルの先頭につけられ た数値部分です。たとえば、移行ファイル 20100611202808_create_books.rb のバージョンは 20100611202808 です。 オプションなどのついていない rake db:migrate コマンドを実行すると、まだ実行されていない up メソッドを全て実行します。もし特定のバージョンを指定すれば、アクティブ・レコードは必要な 移行作業(up もしくは down)を指定されたバージョンに達するまで実行します。たとえば、バージ ョン 20100705000000 に移行するためには、 rake db:migrate VERSION=20100705000000 を実行します。 もし現在のバージョンよりも大きいバージョンが指定されたときは、20100705000000 にいた るまで、移行ファイルの up メソッドが順次実行されます。逆に現在のバージョンよりも小さいバ ージョンが指定されたときは、 20100705000000 を含む移行ファイルの直前までの down メ ソッドが順に実行されます。直近の移行を無効にするためには、 rake db:rollback. を実行します。 ではこのアプリケーションのために何が作成されたか見てみましょう。もし WEBrick サーバーが起 動していなければ、次のコマンドで起動します: <app_home>\bookapp> ruby script/server ブラウザーから http://localhost:3000/books を入力します。図 7.23 のような画面が表示されます。 第 7 章 - Ruby on Rails によるアプリケーション開発 271 図 7.23 Listing books ページ "New book" のリンクをクリックして、新しい書籍のエントリーを追加します。図 7.24 はその画面で す。 図 7.24 新規 book アイテムの作成 RoR アプリケーションから入力した XML 列が、BOOKS 表に正しく保管されていることを確認して ください。図 7.25 では IBM Data Studio を使用しています。 272 DB2 アプリケーション開発入門 図 7.25 IBM Data Studio を使用した XML 文書の表示 ブラウザーから再度 http://localhost:3000/books をアクセスすると、先ほど入力した書籍に関する 情報を見ることができます。図 7.26 は表示例です。RoR が自動的に作成した "Show"、"Edit"、 "Destroy" などの操作リンクを見ることができます。 図 7.26 Listing books ページの出力例 第 7 章 - Ruby on Rails によるアプリケーション開発 273 ここまでで、book リソースに対して書籍情報を追加したり、削除したり、更新したりできるようになり ました。さらに、書籍の一覧を表示させるために新しいリソースを作成する必要があります。そのた めに、以下のコマンドを使って catalog リソースを作成します: <app_home>\bookapp>ruby script/generate controller catalog index このコマンドで、catalog というコントローラーと、index というデフォルトビュー・ページが作成され ます。図 7.27 は実行結果です。 図 7.27 catalog リソースの生成 注: catalog リソースの作成後、Web サーバーを再起動してください。再起動しないと、エラーが返るこ とがあります。 The following actions will build basic logic for the catalog controller to list all the books. Copy and paste the code shown in Listing 7.1 below to the file 以下の作業では、catalog コントローラーが全書籍のリストを表示する基本ロジックを生成します。リ スト 7.1 の内容を、<app_home>\bookapp\app\models\book.rb ファイルにコピーしてください。 (1) class Book < ActiveRecord::Base (2) def self.find_books (3) xquery= "select i.TITLE, i.ID, t.AUTHOR, t.INFO, i.STATUS xmltable('$DESCRIPTION/Info' columns AUTHOR varchar(100) path 'Authors', INFO varchar(400) path 'Description' ) as t" (4) find_by_sql(xquery) end end from books i, 274 DB2 アプリケーション開発入門 リスト 7.1 全ての本をリストする book.rb ファイルの内容 リスト 7.1 では、 (1) Book クラスを定義 (2) catalog で使用する find_books メソッドを宣言 (3) find_books メソッドが使用する xquery ステートメントを記述。xquery ステートメントは、 BOOKS 表 (別名 i)と、XMLTABLE 関数を使って生成した列 (別名 t) のふたつの表から、列 の内容を取得します。XMLTABLE 関数についての詳細は、第 2 章 DB2 pureXML を参照し てください。 (4) SQL を実行するビルトイン・メソッド find_by_sql 注: Ruby on Rails の API に関する詳細な説明については、http://api.rubyonrails.org/ を参照してく ださい。 リスト 7.2 の内容を、 <app_home>\bookapp\app\controllers\catalog_controller.rb ファイルにコピーしてください。このファイルでは、catalog コントローラーが書籍情報をどこから取 得するかを定義しています。 (1) class CatalogController < ApplicationController (2) def index @books=Book.find_books end End リスト 7.2 catalog_controller.rb ファイルの内容 リスト 7.2 では、 (1) CatalogController クラスを定義 (2) index メソッドを定義。Book モデルの中で定義されている find_books の結果を @books インスタンス変数に取得します。 リスト 7.3 の内容を、 <app_home>\bookapp\app\views\catalog\index.html.erb ファイルにコピーしてください。 <h1>DB2 on Campus Book Series</h1> <% for book in @books -%> 第 7 章 - Ruby on Rails によるアプリケーション開発 275 <div class="entry" > <h3><%= link_to h(book.title) ,book ,:id => book%></h3> <h3>Authors</h3> <%= book.author %> <h3>Description</h3> <%= book.info %> <h3>Status</h3> <span class="status" ><%= book.status %></span> </div> <% end %> リスト 7.3 index.html.erb ファイルの内容 この html ファイルでは、書籍情報をどう表示するかビューに教えています。 では実際に動かしてみましょう。ブラウザーから http://localhost:3000/catalog にアクセスしてみま す。図 7.28 のような画面が表示されるはずです。 276 DB2 アプリケーション開発入門 図 7.28 カタログリスト 7.3.2 レイアウトのカスタマイズ ス タ イ ルシ ート (Cascading Style Sheet - CSS) を使 って 画 面 の 見 栄 えを よ く し ま し ょ う 。 <appl_home>\bookapp\public\stylesheets ディレクトリーに、style.css ファイルを作成します。リ スト 7.4 の内容を、style ファイルにコピーしてください。 /* Styles for RoR - DB2 example */ #main { margin-left: 10em; padding-top: 1ex; padding-left: 2em; background: white; 第 7 章 - Ruby on Rails によるアプリケーション開発 277 font-size: 14px; font-family:Arial, sans-serif; } #side { float: left; padding-top: 1em; padding-left: 1em; padding-bottom: 1em; width: 12em; background: #152 ; font-size: 12px; font-family:Verdana, Arial, sans-serif; } #side a { color: #bfb ; font-size: small; } #banner { background: #99cc66 ; padding-top: 10px; padding-bottom: 10px; border-bottom: 1px solid; font-size: 35px; font-family:Verdana, Arial, sans-serif; color: #282 ; text-align: center; } #columns { background: #152 ; } h1 { font: 150% arial; color: #230 ; border-bottom: 3px solid #230 ; } リスト 7.4 style ファイル – CSS ファイル - の内容 278 DB2 アプリケーション開発入門 レイアウトを変更するために、style CSS ファイルを使用します。Rails では、レイアウトは追加の内 容を表示させるためのテンプレートです。今回の例では、ひとつのレイアウトですべての書籍情報 ページと、カタログページのスタイルを定義します。Rails でレイアウトを定義する方法はいくつもあ りますが、ここではもっとも簡単な方法だけを説明します。 <app_home>\bookapp\app\views\layouts ディレクトリーに、コントローラーcatalog と同じ名前 のファイルを作成してください。レイアウトはビューの一部で、html.erb という拡張子をつける必要 がありますので、実際のファイル名は catalog.html.erb となります。catalog コントローラーによっ て表示される全てのビューは、デフォルトではこのレイアウトを使用します。テキスト・エディターを開 いてリスト 7.5 の内容を catalog.html.erb ファイルにコピーしてください。catalog コントローラーに よって表示されるビューのための新しいレイアウトが作成されました。 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>DB Books Series</title> (1) <%= stylesheet_link_tag "style"%> </head> <body id="catalog"> <div id="banner"> <%=@page_title|| "DB2 on Campus Books Series"%> </div> <div id="side"> <a href="http://localhost:3000/catalog" >Home</a><br /> (2) <a href="http://localhost:3000/books" >Books</a><br /> <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /> </div> <div id="main"> <%= yield :layout %> </div> </body> </html> リスト 7.5 catalog.html.erb ファイルの内容 (1) style CSS ファイルを呼び出す方法を示しています。 (2) 全ての書籍情報を操作(作成、更新、削除)する books へのリンクを追加しています。 続いて、 Next, we will do the same for <app_home>\bookapp\app\views\layouts\book.html.erb ファイルに対して同じ作業を行ないます。リスト 7.6 の内容をファイルにコピーしてください。内容は リスト 7.5 とほとんど同じですが、リスト 7.5 では 第 7 章 - Ruby on Rails によるアプリケーション開発 279 <a href="http://localhost:3000/books" >Books</a> となっていた個所が、リスト 7.6 では <a href="http://localhost:3000/catalog" >Catalog</a> に変わっています。 これで、画面左のメニューバーからそれぞれのページへ飛ぶことができるようになりました。 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>DB Books Series</title> <%= stylesheet_link_tag "style"%> </head> <body id="catalog"> <div id="banner"> <%=@page_title|| "Books' Administration"%> </div> <div id="side"> <a href="http://localhost:3000/catalog" >Home</a><br /> <a href="http://localhost:3000/catalog" >Catalog</a> <br /> <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /> </div> <div id="main"> <%= yield :layout %> </div> </body> </html> リスト 7.6 books.html.erb ファイルの内容 ここまでの作業で、すべてのページのレイアウトができました。もしレイアウトを変更したければ、一 個所を変更するだけで充分です。これは"同じことを繰り返さない" ("Do not Repeat Yourself DRY") RoR の特徴の好例です。 ブラウザーを再読み込みすると、図 7.28 や 図 7.29、図 7.30 のように改善されたデザインの画面 が表示されます。 280 DB2 アプリケーション開発入門 図 7.28 レイアウト適用後のカタログリスト 第 7 章 - Ruby on Rails によるアプリケーション開発 281 図 7.29 レイアウト適用後の Book 管理ページ 282 DB2 アプリケーション開発入門 図 7.30 レイアウト適用後の book 更新ページ 7.4 演習問題 この演習問題では、実際に blog アプリケーションを作成します。練習問題を始める前に、Ruby on Rails と DB2 Express-C が正しく導入できていることを確認してください。この作業の中で、 NAME、TITLE、CONTENT という3つの列を持つ POST という表を作成します。 手順: 1. RoR blog アプリケーションを作成します。 rails –d ibm_db blog 2. ibm_db を、ローカルまたはリモートであるかによって構成します。 3.リソースを作成します。 script/generate scaffold Post name:string title:string content:text 4.移行を実行します。 rake db:migrate 第 7 章 - Ruby on Rails によるアプリケーション開発 283 5. Web サーバーを起動し、http://localhost/posts にアクセスします。この本に付属している Exercise_Files_DB2_Application_Developemtn.zip ファイルの内容と比較してみましょう。 7.5 まとめ この章では、ibm_db アダプター/ドライバーと、DB2 データ・サーバーを使って Ruby on Rails ア プリケーションを開発する方法の基礎について学びました。まず Windows 環境で Ruby on Rails を稼働させるために必要なセットアップについて解説し、ついで database.yml ファイルで DB2 デ ータベースに接続するための構成について説明しました。最終的には、シンプルな Web アプリケ ーションを作成できるようになりました。サンプル・アプリケーションでは、各書籍の情報を保管する ために XML データ型の列を使っています。 7.6 確認問題 1. Ruby on Rails とは? gem とは? 2. DB2 の RoR ドライバーとアダプターを導入する方法は? 3. RoR はどのように DB2 とやりとりをしていますか? 4. DB2 と接続するために必要な database.yml ファイルの構成方法は? 5. RoR で XML をデータ型として使用できますか? 6. RubyGems に関する次記述のうち、間違っているのはどれでしょう? A. 標準化されたパッケージ・フォーマットで作成されたホスティング・パッケージのための リポジトリーである。 B. 同時に複数のバージョンのライブラリーを導入し、管理することができる。 C. 新しいバージョンを導入する前に、古いバージョンを削除する必要がある。 D. RubyGems は、パッケージを照会し、導入し、削除し、操作するためのエンド・ユー ザー・ツールである。 E. 上記のいずれでもない 7. 次のアイテムのうち、gem でないものはどれでしょう? A. Ruby B. Rails C. Rake D. IBM_DB E. 上記のいずれでもない 8. IBM_DB とアクティブ・レコードに関する次の記述のうち、正しいものはどれでしょう? A. IBM_DB はドライバーとアダプターを含む。ドライバーは、アクティブ・レコードと直接 対話する。 284 DB2 アプリケーション開発入門 B. アクティブ・レコードは IBM_DB の一部である。 C. IBM_DB アダプターは IBM データ・サーバーと接続するために、IBM Driver for ODBC and CLI を使用する。 D. IBM_DB を利用可能にするために、DB2 クライアントとサーバーの両方を PC に導 入する必要がある。 E. 上記のいずれでもない 9. Linux 環境に導入されたリモートの DB2 サーバーに接続する際、database.yml 構成フ ァイルにおいて必須でないものはどれでしょう? A. Account B. Database C. Password D. Username E. 上記のいずれでもない 10. Linux 環境に ibm_db を導入する際に、もっとも適切な順序はどれでしょう? a. root ユーザーで shell を起動する。 b. 環境変数を設定する。 c. ibm_db を導入する。 d. DB2 プロファイルを実行する。 e. root ユーザーで起動した shell を終了する。 A. a->b->c->d->e B. a->b->d->c->e C. a->d->b->c->e D. a->c->d->b->e E. 上記のいずれでもない 8 第 8 章 – PHP によるアプリケーション開発 PHP(PHP ハイパーテキスト・プリプロセッサー)はもともと Web アプリケーション開発のためのイン タープリターであり、汎用に使えるオープン・ソースのスクリプト・プログラミング言語です。Rasmus Lerdorf によって最初のバージョンの PHP が作られ、1995 年からオープン・ソースライセンスの元 で開発が続けられています。 PHP は通常 Web サーバー上で、動的な Web ページコンテンツを作るために PHP ランタイムに よってそのコードが実行されます。PHP はコマンド・ラインによるスクリプトやクライアント・サイドの GUI アプリケーションでも使われます。PHP はほとんどの Web サーバー、多数のオペレーティン グ・システムとプラットフォームに展開することができ、数々のデータベース・マネジメントシステムと 共に使うことができます。PHP は無償で入手でき、PHP グループはユーザーがビルド、カスタマイ ズ、それぞれの用途に沿った拡張をできるように完全なソース・コードを提供しています。 この章では以下の内容についてご説明します: z DB2 と動作させるための PHP 環境の設定 z DB2 と動作する PHP アプリケーションの開発 8.1 PHP-DB2 アプリケーション:概要 図 8.1 は PHP-DB2 アプリケーションの概要を示しています。図中で、ユーザーは Web ブラウザ ーを開き、PHPS スクリプトを呼び出すページを指定します。リクエストは PHP コードが実行される Web サーバーで受信され、PHP コードが実行されます。リクエストが DB2 のデータにアクセスす る必要がある場合は、PHP は DB2 データベースに接続して必要なデータを取り出し、更新あるい は削除します。その後、出力を返す場合は HTML として Web ブラウザーに送信されます。 286 DB2 アプリケーション開発入門 図 8.1 PHP、Web サーバーおよび DB2 間の連携 PHP は主にファイルあるいはテキストを含むストリームまたは PHP の instruction を入力としてフィ ルタとして作用し、他のデータストリームを出力します。最もよく使われる出力は HTML です。PHP スクリプトは実行時に PHP エンジンによってコンパイルされることで、実行スピードが早くなってい ます。PHP スクリプトは事前に PHP コンパイラーを使ってコンパイルしておくこともできます。 8.2 環境の設定 PHP を使い始めるには、Web サーバー、PHP そして DB2 データベース・サーバーを導入する必 要があります。Web サーバーとデータベース・サーバーが異なるマシンの場合、DB2 クライアント も Web サーバー上に導入する必要があります。 この章では、各コンポーネントを個別にダウンロード・導入する手動での環境構築方法を説明しま す。また、Zend Core と呼ばれる、Zend 社がサポートする無償版の PHP を使ったより簡単な環境 構築方法もあわせて説明します。Zend Core は Web サーバーと必要なドライバー、DB2 Express-C と動作するライブラリーを同梱しており、とても簡単に導入・構成できます。 8.2.1 手動での PHP 環境の構築 各コンポーネントを個別に導入して手動で環境を構築したい場合は、以下の手順に従います。 1. Apache HTTP サーバーを導入します。http://httpd.apache.org/download.cgi から使用する オペレーティング・システムにあったソース・コードをダウンロードします。導入手順は同じ URL に記載されています。 第 8 章 – PHP によるアプリケーション開発 287 2. DB2 Express-C を導入します。http://www.ibm.com/db2/express からダウンロードします。 3. Linux を使う場合、gcc コンパイラーと以下のパッケージが導入されていることを確認します: apache-devel, autoconf, automake, bison, flex, gcc, and libxml2-devel package 4. PHP コードが配置されている Web サーバーとデータベース・サーバーが異なるマシン上にあ る場合、以下の DB2 クライアントのどれかをダウンロードして導入します: IBM Data Server Driver Package, IBM Data Server Client, あるいは IBM Data Server Driver for ODBC and CLI. (http://www-01.ibm.com/support/docview.wss?rs=4020&uid=swg21385217 か らダウンロードします。) 5. 最新バージョンの Linux/UNIX, Windows 用 PHP を http://www.php.net からダウンロードし ます。執筆時の PHP 最新バージョンは 5.3 です。以下の章で説明するとおり、Linux/UNIX、 Windows 上で導入、設定します。 8.2.1.1 Linux/UNIX 上での PHP 環境の構築 1. 事前にダウンロードした PHP パッケージを以下のコマンドで展開します: tar -xjf php5.x.x.tar.bz2 2. 新たに作成された php-5.x.x ディレクトリーに移動します。 3. configure コマンドで makefile を設定します。あなたの環境の PHP に含めるフィーチャーや 拡張機能を指定します。configure コマンドには典型的に以下のオプションを含めます: ./configure --enable-cli--disable-cgi --with-apxs2=/usr/sbin/apxs2 --with-zlib --with-pdoibm=<sqllib> --with-pdo-ibm=<sqllib> オプションは DB2 CLI ライブラリーが DB2 データベースへのアクセ スに使用する pdo_ibm ドライバーを有効にします。<sqllib> は DB2 を導入したディレクトリー を指定します。pdo_ibm ドライバーについてはこの章で後ほど説明します。 4. make コマンドでファイルをコンパイルします。 5. make install コマンドでファイルをインストールします。configure コマンドで PHP インストー ル・ディレクトリーの設定によっては、コマンド実行の成功のために root 権限が必要になります。 このコマンドで、実行可能形式ファイルが導入され、Apache HTTP サーバーの設定が PHP をサポートするように更新されます。 6. ibm_db2 拡張を導入します。root 権限で以下のコマンドを実行します: pecl install ibm_db2 7. PHP を導入した設定ファイルパス上に php.ini-recommended ファイルをコピーします。設定 ファイルパスを確認するには、php -i コマンドを実行し、php.ini キーワードを探します。php.ini ファイルとしてファイル名を変更します。 8. 新しくファイル名を変更した php.ini ファイルをテキスト・エディターで開き、以下の行を追加し ます。"instance" は Linux/UNIX 上での DB2 インスタンス名を指します。 288 DB2 アプリケーション開発入門 pdo_ibm の DB2 環境を設定する: PDO_IBM.db2_instance_name=instance ibm_db2 拡張を有効にして DB2 環境を設定する: extension=ibm_db2.so ibm_db2.instance_name=instance 9. 設定を反映させるため Apache HTTP サーバーを再起動します。 8.2.1.2 Windows 上での PHP 環境の構築 1. ダウンロードした PHP の zip パッケージをインストール・ディレクトリーに展開します。 2. PECL パッケージコレクションの zip パッケージをインストール・ディレクトリー以下の\ext\ サ ブ・ディレクトリーに展開します。 3. php.ini-recommended をコピーしてファイル名 php.ini としてインストール・ディレクトリー以下 にファイルを作成します。 4. php.ini ファイルをテキスト・エディターで開き、以下の行を追加します。 pdo_ibm ドライバーと PDO 拡張を有効にする: extension=php_pdo.dll extension=php_pdo_ibm.dll ibm_db2 拡張を有効にする: extension=php_ibm_db2.dll 5. Apache HTTP Server 2.x で PHP サポートを有効にするために、httpd.conf ファイルに以下 の行を追加します。(phpdir は PHP のインストール・ディレクトリーです。): LoadModule php5_module 'phpdir/php5apache2.dll' AddType application/x-httpd-php .php PHPIniDir 'phpdir' 6. 設定を反映させるため Apache HTTP サーバーを再起動します。 注: Windows については、Web サーバー(この場合 Apache)および PHP のいずれについてもインス トール用バイナリーよりも*.msi ファイルのダウンロードを推奨します。 8.2 Zend Core を使用した環境の構築 第 8 章 – PHP によるアプリケーション開発 289 Zend Core は Zend 社がサポート・認定するバージョンの PHP を含む無償の製品です。Apache Web サーバーと DB2 Express-C に必要なドライバーとライブラリーも含みます。Zend Core をダ ウンロードするには http://www.zend.com/en/products/platform/downloads を参照します。 ダウンロードのために適切なプラットフォーム(Linux または Windows)を選択します。導入は非常 に簡単なため、このセクションでは記述しません。通常、全てデフォルトの設定に従うだけで十分で す。 8.3 PHP-DB2 アプリケーション開発 このセクションでは、PHPアプリケーションからDB2データベースへのアクセス方法について述べま す。はじめに、この目的のために使える異なる拡張について述べます。 8.3.1 DB2 で使える PHP 拡張 DB2 で使える PHP 拡張は 3 つありますが、最初の 2 つを推奨します。 ibm_db2 IBM が作成、保守、サポートする、DB2 にアクセスするための PHP 拡張です。 pdo_ibm / pdo_odbc PHP5.1 から導入された標準オブジェクト指向データベース・インターフェース経由で DB2 へのアクセスを提供する PHP データ・オブジェクト(PDO9 拡張です。DB2 への下位イン ターフェースとして CLI を利用しています。あるいは、ODBC ドライバーまたは DB2 CLI を 利用する pdo_odbc を使うこともできます。 Unified ODBC 過去 DB2 データベース・システムへのアクセスを提供してきた拡張です。ibm_db2 と pdo_ibm のほうが UnifiedODBC と比べて優れたパフォーマンスと安定性を提供している ため、この拡張を使って新規にアプリケーション開発をすることは推奨されていません。こ の本ではこの拡張については言及しません。 注: “odbc_”で始まる関数名は全て Unified ODBC、“db2_”で始まる始まる関数名は ibm_db2 と、残り の部分の名前は両方で一致しているため、アプリケーションコード内の全ての“odbc_” を “db2_” に変更するのとほぼ同様の簡単さで、既に Unified ODBC を使って書かれたアプリケーションを ibm_db2 拡張 API を使って非常に容易に移植することができます。 8.3.2 ibm_db2 拡張を使った PHP アプリケーション開発 Linux/UNIXを使って開発している場合、ibm_db2を使う前にphp.ini設定ファイルがPHPから接続 したいDB2インスタンスに設定されていることを確認します。これは、DBの接続と照会のために PHPは個別のインスタンスのライブラリーを参照するためです。Linux/Unixでは、DB2INSTANCE 環境変数を上書きしますが、Windows環境ではこのオプションは無視されます。 290 DB2 アプリケーション開発入門 該当のエントリーが見つからない場合、(デフォルトのインスタンス名db2inst1を使用すると仮定し て)php.iniファイルに以下のようにエントリーを作成します: [ibm_db2] ibm_db2.instance_name=db2inst1 php.ini ファイル内で変更できるその他のグローバル変数は、PHP ドライバーのバイナリー・データ の扱い方を変更することができる ibm_db2.binmode です。文法は以下の通りで、n=1,2,3 のい ずれかの値をとります。 ibm_db2.binmode = “n” n=1の場合、DB2_BINARY定数が設定され、全てのバイナリー・データはそのままの形で扱われ ます。n=2の場合、DB2_CONVERT定数が設定され、全てのバイナリー・データはibm_db2ドライ バーにASCIIに変換されます。n=3の場合、DB2_PASSTHRU定数が設定され、全てのバイナリ ー・データはnull値に変換されます。 8.3.2.1 プログラム・フロー PHPプログラムで実行する典型的なステップは以下の通りです: 1. データベースへ接続する 2. ステートメントを準備・実行する 3. 結果を処理する 4. リソースを開放する PHPは接続とステートメントにハンドラーを使用します。ハンドラーは接続後あるいはステートメント 実行時に設定される変数で、接続と実行されるステートメントの関係を確立するのに便利です。 8.3.2.2 データベースへ接続する DB2 データベースに接続するには 2 つの方法があります。 ・非永続性接続(db2_connect) ・永続性接続(db2_pconnect) その名が示すとおり、非永続性接続は毎 db2_close 後、あるいは接続リソースが NULL に設定さ れた場合、あるいはスクリプトが終了した際に接続を切断してリソースを開放します。データベース セッションが頻繁に作成・開放された場合はパフォーマンスに影響します。しかし、 INSERT,UPDATE, DELETE といったオペレーションを実行している場合は非永続性接続を使う ほうが賢明です。 永続性接続の場合、db2_close 後やスクリプト終了後もリソースは開放されません。新規の接続が 要求された場合は常に PHP は同じ認証情報を使った接続を再利用しようとします。 第 8 章 – PHP によるアプリケーション開発 291 接続構文はデータベースが DB2 でカタログされているか否かによって異なります。 8.3.2.2.1 カタログされたデータベースに接続する カタログされたデータベースへ接続するには、db2_connect の引数としてデータベース・エイリアス 名、ユーザーID、データベース・サーバーのパスワードが必要になります。リスト 8.1 は SAMPLE データベースへの接続例を示しています。 <?php $db_name = 'Sample'; $usr_name = 'db2inst1'; $password = '123456'; // For persistent connection, change db2_connect to db2_pconnect (1) $conn_resource = db2_connect($db_name, $usr_name, $password); if ($conn_resource) { echo 'Connection to database succeeded.'; (2) db2_close($conn_resource); } else { echo 'Connection to database failed.'; echo 'SQLSTATE value: ' . db2_conn_error(); echo 'with Message: ' . db2_conn_errormsg(); } ?> リスト 8.1 カタログされたデータベースに接続する 上記リストでは、 1. db2_connect()メソッドが接続を確保した後、 conn_resource が接続ハンドラーとして割り当 てられます。 2. 以前に獲得した接続リソースをクローズ・開放するために db2_close() メソッドを使用します。 8.2.2.2 カタログされていないデータベースに接続する カタログされていないリモート・データベースに接続するためには、接続文字列にデータベース・サ ーバーの詳細を渡し、connection 関数にパラメーターとして渡す必要があります。接続文字列は 以下のフォーマットになります。 DRIVER={IBM DB2 ODBC DRIVER};DATABASE=database name;HOSTNAME=host 292 DB2 アプリケーション開発入門 name;PORT=port;PROTOCOL=TCPIP;UID=user name;PWD=password; 8.3.2.3 SQL文の準備と実行 SQL文を準備・実行する間に、以下のトランザクションの性質について決定する必要があります。 ・ 使用するカーソルタイプ ・ エラーのキャッチ方法 ・ 使用する分離レベル 8.3.2.3.1 使用するカーソル・タイプ PHP の ibm_db2 モジュールでは 2 種類のカーソル・タイプをサポートします。 ・ フォワードのみカーソル PHP アプリケーションにおける ibm_db2 モジュールのデフォルト・カーソルです。カーソ ルは行ごとに結果セットを一方向に取り出します。このカーソルはデータベースに対して 読み取り専用オペレーションを実行したいときに理想的なカーソルです。 ・ スクロール可能カーソル ibm_db2 拡張はキーセットによるクロール可能カーソルを使ってスクロール可能カーソル を実装しています。このカーソルは下層のデータを検知し、変更することができます。カ ーソルがオープンされた際に、DB2 はキーが保存されているキーセットを作成し、カーソ ルでの行の順番を決定するのに利用します。フェッチ処理が進むにつれて、カーソルは 最新の値をデータベースから取り出すためにキーセット内のキーをスクロールしていきま す。 8.3.2.3.2 エラーの捕捉方法 作成するアプリケーションは SQL やデータベース・エラーを含む全ての例外を十分に捕捉・例示 すべきです。そのために、プログラムはデータベース関数の返り値を確認し、エラーがあった場合 に は SQLSTATE を プ リ ン ト す べ き で す 。 エ ラ ー が 起 こ っ た 際 の 詳 細 を 表 示 す る に は db2_stmt_error および db2_stmt_errormsg を使います。リスト 8.2 はその例を示します。 $stmt = db2_exec($conn_resource, $sql); if (!$stmt) { echo 'SQLSTATE value: ' . db2_stmt_error(); echo 'with Message: ' . db2_stmt_errormsg(); } リスト 8.2 エラーの詳細を表示する 8.3.2.3.3 使用する分離レベル PHPプログラムでは分離レベルの変更に2つの方法を使用することができます: 第 8 章 – PHP によるアプリケーション開発 1. 293 特定の SQL 文が指定した分離レベルで実行されるよう、SQL 文に WITH 節を追加 します。リスト 8.3 はその例を示します。 // With connection being made and connection resource // is in $conn_resource $sql = 'SELECT c_id FROM customer WITH UR'; $stmt = db2_exec($conn_resource, $sql); リスト 8.3 PHP の ibm_db2 で分離レベルをセットする 上記の例では、SQL文は分離レベルURを使って実行されます。 2. CURRENT ISOLATION特殊レジスターを変更する 特定の分離レベルを全セッションで使うために、CURRENT ISOLATION特殊レジスター をUR, CS,RS あるいは RR に設定します。DB2特殊レジスターの値はデフォルトの分離 レベルを上書きします。スクリプトの末尾まで分離レベルをデフォルト値(CS)にリセットす るのは良い例です。リスト8.4がその例です。 // With connection being made and connection resource // is in $conn_resource (1) $currentiso = 'SET CURRENT ISOLATION LEVEL TO RR'; (2) $sql = 'SELECT c_id FROM customer'; (3) $stmt = db2_exec($conn_resource, $currentiso); (4) $stmt = db2_exec($conn_resource, $sql); // Execute other SQL statements $currentiso = 'SET CURRENT ISOLATION LEVEL TO CS'; $stmt = db2_exec($conn_resource, $currentiso); リスト 8.4 CURRENT ISOLATION 特殊レジスターで分離レベルをセットする 上のリストでは、 (1) currentiso で分離レベルを RR に設定します。 (2) sql には実行する SQL 文を割り当てます。 (3) stmt には db2_exec()メソッドの返り値が割り当てられます。接続リソース変数と分離 レベルをこのコマンド実行時に渡す必要があります。 (4) stmt には db2_exec()メソッドの返り値が割り当てられます。接続リソース変数と分離 レベルをこのコマンド実行時に渡す必要があります。 8.3.2.3.4 SQL 文の準備・実行 SQL文の準備と実行の概要についてのいくつかのステップは、既に1章で説明しています。PHP におけるibm_db2拡張では以下の通り実行されます。 準備と実行を同時に行う 294 DB2 アプリケーション開発入門 準備と実行をひとつのステップで行うにはひとつの関数だけ使用しますが、その方法では同じSQL文が一回 以上実行される場合に最適なパフォーマンスが得られません。接続リソースと共にdb2_exec関数にSQL文を 渡す方法は、SQL文の準備と実行を一ステップで行います。この一ステップで行う方法は、異なるカーソル・タ イプで利用できます: ・ 準備と実行をデフォルト・カーソルで実行するには: $sql = 'SELECT c_id FROM customer'; $stmt = db2_exec($conn_resource, $sql); ・ 異なるタイプのカーソルパラメーターで準備と実行をするには:デフォルトのフォワードのみカーソル をスクロール可能カーソルに変更するために追加のパラメーターを使用することができます。そのた めには、連想配列で DB2_SCROLLABLE を 3 番目のパラメーターとして以下の通り渡す必要が あります: $stmt = db2_exec($conn_resource, $sql, array('cursor' => DB2_SCROLLABLE)); 準備し、そして実行する セキュリティーとパフォーマンスの観点からは、準備して実行する方法が SQL 文の実行には最適 です。この手順に含まれるステップは以下の通りです: 1. SQL 文を準備する db2_prepare 関数を使ってパラメーター・マーカーあり・なしの両方の SQL 文を準備すること ができます。また、行のフェッチを行う際にどのカーソル・タイプを使うかを指定することができ ます。例えば、以下の SQL 文はパラメーター・マーカーを使います: SELECT c_name FROM CUSTOMERS WHERE c_id = ? and c_phone = ? パラメーター・マーカーの値("?")は db2_prepare 関数を使って結果を引き出すためにデー タベース・エンジンに対して提供されます。 2. パラメーターをバインドする 準備された SQL 文に PHP 変数を動的にバインドするには、db2_bind_param 関数を使い ます。この方法はパラメータータイプやデータタイプ、述部および準備された SQL 文とバイン ドした変数のスケールを指定できるため、db2_execute 関数で変数の配列をバインドするより よ り パ ワ フ ル で す 。 ラ ー ジ ・ オ ブ ジ ェ ク ト を 挿 入 し て CALL 文 を 呼 ぶ 以 外 の 場 合 に は DB2_PARAM_IN パラメーターが全ての SQL 文で使われます。一度パラメーターがバインド されると、メモリーに割り当てられて準備された SQL 文はその値と共に実行されます。 (db2_prepare 関数が呼ばれた際には、値はまだ与えられていません。) PHP では、パラメー ターの値はバインド後に与えることもできます。リスト 8.6 は準備と二つのパラメーター・マーカ ーのバインド(ひとつは integer、もうひとつは character)と、SQL 文の実行の一連の例を示し ます。 <?php $database = 'sample'; 第 8 章 – PHP によるアプリケーション開発 295 $user = ''; $password = ''; $conn = db2_connect($database, $user, $password); if ($conn) { $statement = 'SELECT c_id, c_name, c_email FROM db2inst1.customer WHERE c_id > ? OR c_name NOT LIKE ?'; // prepare the SQL statement $stmt = db2_prepare($conn, $statement); $id = 100; (1) db2_bind_param($stmt, 1, "id", DB2_PARAM_IN); db2_bind_param($stmt, 2, "name", DB2_PARAM_IN, DB2_CHAR); $name = 'MyName'; $result = db2_execute($stmt); (2) while ($object = db2_fetch_object($stmt)) { // Iterate through results echo 'ID: ' . $object->C_ID; echo 'Name: ' . $object->C_NAME; echo 'Email: ' . $object->C_EMAIL; } if (!$result) { (3) db2_rollback($conn); echo 'Execution failed. '; echo 'SQLSTATE value: ' . db2_stmt_error(); echo 'with Message: ' . db2_stmt_errormsg(); } db2_free_stmt($stmt); db2_close($conn); } else { echo 'Connection to database failed.'; echo 'SQLSTATE value: ' . db2_conn_error(); echo 'with Message: ' . db2_conn_errormsg(); } ?> リスト 8.6 準備、バインドして SQL 文を実行する 上のリストでは、以下を実行しています: 1. db2_bind_param 関数は PHP 変数を SQL 文のパラメーターにバインドします。 2. db2_fetch_object 関数はフェッチされた行の列を表すプロパティーと共にオブジェクトを返 します。そしてその返されたオブジェクトを保持するために変数のオブジェクトを使用します。 3. db2_rollback 関数は指定された接続リソースの進行中のトランザクションをロールバックし、 新しいトランザクションを開始します。PHP アプリケーションは通常 AUTOCOMMIT モードを 296 DB2 アプリケーション開発入門 デフォルトとするため、通常 db2_rollback 関数は接続リソースに対して AUTOCOMMIT が 無効に設定されるまで影響を与えません。 注: 指定された接続リソースが永続接続の場合、永続接続を利用する全てのアプリケーションの進行 中の全てのトランザクションはロールバックされます。このため、トランザクションを必要とするアプリ ケーションでの永続接続の使用は推奨されません。 加えて、変数をバインドする前に以下の点に注意します: ・ PHP 変数名はダブル・クォート(“)で囲み、$マークを含まない”variable”とする必要が あります。 ・ バインドされた変数の位置変数を確認します。Index は 1 からスタートすべきです。 ・ INTEGER および VARCHAR 以外の変数については、DB2_BINARY, DB2_CHAR, DB2_DOUBLE, あるいは DB2_LONG データタイプを使用することを推奨します。 DECIMAL データタイプを使う他の例では、db2_bind_param 関数で DB2_LONG パラメータ ーを使う必要があります。以下の文では、amount が DECIMAL 型変数です。 // Here we bind a decimal (10,2) type variable amount db2_bind_param($stmt, 1, "amount", DB2_PARAM_IN,DB2_LONG); 3. クエリーを実行する SQL 文を準備した後、db2_bind_param 関数でパラメーターをバインドします。クエリーが準備さ れバインドされた情報が db2_execute 関数の入力として渡された後、ステートメントリソースが獲 得され、SQL 文が実行されます。リスト 8.6 にこの方法のサンプル・プログラムを見ることができます。 別の方法として、パラメーターを配列として直接 db2_execute 関数に渡します。この場合、配列 変数を第二のパラメーターとして db2_bind_param 関数に渡す必要があります。 クエリーが実行された時点で、以下の関数のいずれかを使って結果セットを得るためにステートメ ントリソースを使うことができます: a. db2_fetch_array b. db2_fetch_assoc c. db2_fetch_both d. db2_fetch_object e. db2_fetch_row これらのいくつかの関数については次のセクションで詳細を説明します。 第 8 章 – PHP によるアプリケーション開発 297 8.3.2.4 結果を処理する SQL 文が結果セットを返した際に、行を取り出すいくつかの方法があります。結果セットを行ごとに データ構造にフェッチするか、スクロール可能カーソルを使って結果セットをスクロールし、必要な 行をフェッチする方法です 8.3.2.4.1 db2_fetch_array 関数を使う この関数は、結果セットの行を取り出し列番号の配列に格納するために使います。この関数はステ ートメントリソースを入力とし、行が返されない場合に偽を返します。リスト 8.7 は例を示します。 while ($row = db2_fetch_array($stmt)) { printf("%d %s %s", $row[0], $row[1], $row[2]); } リスト 8.7 db2_fetch_array 関数を使う 8.3.2.4.2 db2_fetch_assoc 関数を使う この関数は、結果セットの行を取り出し列名の配列に格納するために使います。この関数は行が返 されない場合に偽を返します。リスト 8.8 は例を示します。 $sql = 'SELECT * FROM customer WHERE c_id >= ?'; $stmt = db2_prepare($conn_resource, $sql); if (!$stmt) { echo 'The prepare failed. '; echo 'SQLSTATE value: ' . db2_stmt_error(); echo 'with Message: ' . db2_stmt_errormsg(); } else { db2_bind_param($stmt, 1, "c_id", DB2_PARAM_IN); $c_id = 100; $result = db2_execute($stmt); if (!$result) { echo 'The execute failed. '; echo 'SQLSTATE value: ' . db2_stmt_error(); echo 'with Message: ' . db2_stmt_errormsg(); } } while ($row = db2_fetch_assoc($stmt)) { printf("%d %s %s ", $row['C_ID'], $row['C_NAME'], $row['C_EMAIL']); } リスト 8.8 db2_fetch_assoc 関数を使う 列は列名で索引付けされているため、列名の大文字小文字の区別は問いません。デフォルトの列 名の大文字小文字の区別は以下の値のうちのいずれかを取る DB2_ATTR_CASE 分で変更す ることができます: 298 DB2 アプリケーション開発入門 DB2_CASE_NATURAL: DB2 が返す列名を使います DB2_CASE_LOWER: 列名は小文字に強制変換されます DB2_CASE_UPPER: 列名は大文字に強制変換されます 例えば、列名を小文字に強制変換したい場合は以下のようになります: $stmt = db2_prepare($conn_resource, $sql, array('DB2_ATTR_CASE' => DB2_CASE_LOWER)); 8.3.2.4.3 db2_fetch_both 関数を使う この関数は列番号・列名の両方で索引付けされた配列を戻します。リスト 8.9 は例を示します。 while ($row = db2_fetch_both($stmt)) { printf("%d %s %s", $row[0], $row['C_NAME'], $row['C_EMAIL']); } リスト 8.9 db2_fetch_both 関数を使う 8.3.2.4.4 db2_fetch_object 関数を使う この関数は取り出された各行のオブジェクトを返すことに使用できます。オブジェクトの各プロパテ ィーは返された各列です。リスト 8.10 は例を示します。 while ($row = db2_fetch_object($stmt)) { printf("%d %s %s", $row->C_ID, $row->C_NAME, $row->C_EMAIL); } リスト 8.10 db2_fetch_object 関数を使う 8.3.2.4.5 db2_fetch_row 関数を使う この関数は結果セットを反復する、あるいはスクロール可能カーソルを使っている場合に指定され た行番号に進めることに使用できます。リスト 8.11 は db2_fetch_row 関数を使って結果セットの 全ての行を取り出す方法を示します。 while ($row = db2_fetch_row($stmt)) { printf( "%d %d %s", db2_result($stmt, 0), db2_result($stmt, 1), db2_result($stmt, 2) ); } リスト 8.11 db2_fetch_row 関数を使う 8.3.2.4.6 メタデータを取り出す 第 8 章 – PHP によるアプリケーション開発 299 結果セットで返された列に関するメタデータを取り出すことができるいくつかの関数があります。そ のうちの便利ないくつかの関数は以下の通りです: db2_num_rows 関数は SQL 文によって削除、挿入あるいは更新された行数あるいは SQL 文で返された行数を返します。しかし、SQL 操作を実行するためにスクロール可能カ ーソルを使っている場合、db2_num_rows 関数の使用は避け、select 文(‘SELECT COUNT(*) FROM table WHERE condition‘)を使用すべきです。 db2_fetch_ 関数は真偽値を返し、結果セットの終了を確認することができます。 db2_field_ で始まるメタデータ関数は SQL 文で返されるフィールドに関する全てのタイ プの情報を引き出すことができます。その情報は列名、データ型、述部およびデシマル型 のスケールと深さです。これらの関数は成功した場合それらの情報を含む文字列を返しま す。それらの関数に必要な変数はステートメントリソースと 0 から始まる列番号あるいは列 名です。 db2_num_fields 関数は SELECT 文で返される列数を得るのに役立ちます。動的に生 成された照会文とストアード・プロシージャーの列数を確認することに使われます。 リスト 8.12 はその例を示します。 $sql = 'SELECT * FROM customer WHERE c_id > ?'; $stmt = db2_prepare($conn_resource, $sql); // The number of columns in the statement echo 'Num fields: ' . db2_num_fields($stmt) . ' in the statement'; if (!$stmt) { echo 'The prepare failed. '; echo 'SQLSTATE value: ' . db2_stmt_error(); echo 'with Message: ' . db2_stmt_errormsg(); } else { db2_bind_param($stmt, 1, "c_id", DB2_PARAM_IN); $c_id = 100; $result = db2_execute($stmt); if (!$result) { echo 'The execute failed. '; echo 'SQLSTATE value: ' . db2_stmt_error(); echo 'with Message: ' . db2_stmt_errormsg(); } } リスト 8.12 metadata 関数を使う 8.3.2.5 リソースを開放する db2_free_stmt 関数を使ってステートメントリソースを開放し、db2_free_result 関数を使って結 果セットリソースを開放することができます。これらの関数を使ってリソースを開放しなかった場合に は、スクリプトが終了した後自動的に両方のリソースが開放されます。 300 DB2 アプリケーション開発入門 db2_close DB2 関数は db2_connect 関数によって割り当てられた接続リソースを開放できます。 永続接続を確立するために db2_pconnect 関数が使われた場合、db2_close 要求は無視され、 接続リソースは次回の同様の接続に使用されます。リスト 8.13 は db2_close の使用例を示しま す。 $result = db2_close($conn_resource); if ($result) { echo 'Connection was successfully closed.'; } リスト 8.13 db2_close()メソッドを使う 8.3.3 PDO_IBM/PDO_ODBC を使った PHP 開発 この章では pdo_ibm ドライバーを使った PHP 開発について述べます。設定変数名におけるいく つかの違いを除き、pdo_ibm と pdo_odbc を使った PHP 開発はまさに同じです。DB2 の導入と 設定、および PHP と Apache とこれらのドライバーの導入の後、PDO を DB2 と一緒に使うために php.ini ファイルのいくつかの変数を編集する必要があるかもしれません。いくつかの変数につい ては以前の章ですでに述べていますが、さらなる詳細は以下の通りです: pdo_odbc.db2_instance_name このエントリーは PHP に DB2 ライブラリーのロケーションを示すために Linux と UNIX で の導入の際に含まれなければなりません。以下はインスタンス名が db2inst1 の場合の設 定例です: pdo_ibmを使う場合: [PDO_IBM instance name] pdo_ibm.db2_instance_name= db2inst1 PDO_ODBCを使う場合: [PDO_ODBC instance name] pdo_odbc.db2_instance_name= db2inst1 pdo_odbc.connection_pooling 接続プールは以前に確立された古い接続を再利用することによりデータベース・アプリケ ーションのパフォーマンス改善に役立ちます。接続が短時間に確立される場合には特に 役立ちます。pdo_odbc.connection_pooling の値は接続プールのレベルを設定する ために設定されます。表 8.1 に異なるレベルが述べられています: 接続プールのレベル 説明 Strict 接続認証がクローズされた接続と完全に一致する場 合に接続が再利用されます。接続プールを有効にす 第 8 章 – PHP によるアプリケーション開発 301 る場合はこのオプションの使用を推奨します。 Relaxed 接続文字列が一致する接続は再利用され、全ての接 続属性がチェックされるわけではありません。 Off 接続プールは使用されません。 以下は php.ini ファイル内で接続プールが relaxed で設定された場合の例を示します。 [PDO connection pooling] pdo_ibm.connection_pooling = relaxed or [PDO connection pooling] pdo_odbc.connection_pooling = relaxed pdo.dsn.* データ・ソース名(DSN)は ODBC あるいは CLI ドライバー経由のデータベース接続に関 連した情報を含みます。DSN はデータベース名、データベースドライバー、ユーザー名、 パスワードや他の情報を含みます。php.ini ファイルで DSN 文字列の別名を作成すること ができます。別名を作るには、pdo.dsn で始まる、その DSN と同一とみなす別名を指定 した各別名のエントリーを作成します。このシナリオでの DSN はカタログされた、あるいは カタログされていない DB2 データベースのいずれを指定することもできます。以下の例は SAMPLE データベースに接続したい場合の DSN 別名エントリーを示します: For pdo_ibm: [DSN alias for pdo_db2] pdo.dsn.dealerbase="ibm:sample" For pdo_odbc: [DSN alias for pdo_db2] pdo.dsn.dealerbase=”odbc:sample” php.ini ファイルにエントリーが作成された時点で、以下のように別名を参照してデータベ ースに接続することができます: $dbh = new PDO("dealerbase"); 8.3.3.1 プログラム・フロー PDOプログラミングはオブジェクト指向コンセプトを使用しています。接続がDB2データベースに対して確立し たときに、PDO基本クラスのインスタンスが作成されます。このインスタンスがデータベースハンドルとして動作 し、追ってデータベースに対してさらにアクティビティが実行される際に使用されます。データベース操作時に 以下のように分類される異なるオブジェクトが作成されます: 接続オブジェクト(PDO インスタンス) 302 DB2 アプリケーション開発入門 ステートメント・オブジェクト(PDOStatement インスタンス) 例外(PDOException インスタンス) トランザクションを処理する PDO プログラムの典型的なプログラム・フローは以下の通りです: 1. データベースに接続する 2. SQL 文を準備・実行する 3. 結果を処理する 4. リソースを開放する 8.3.3.2 データベースに接続する データベースへの接続は PDO クラスのコンストラクターが new PDO() を使って呼び出された際に取 得されます。コンストラクターに与える変数には 4 つの変数があります: データベース名 (DSN) ユーザー名 パスワード ドライバーオプション DSN はデータベースへの接続に必要な、使用されるドライバータイプ(DB2 の場合は CLI/ODBC)、 データ・ソース名、接続認証情報(ユーザ名およびパスワード)といった情報を含みます。必要となる DSN パラメーターはカタログされたデータベースに接続するかカタログされていないデータベース に接続するかに依存します。DB2 データベースに接続している場合、カタログされた接続を使うほ うが望ましいでしょう。以下はデータベース名が SAMPLE、ユーザーID が db2inst1、パスワードが 123 の場合に DSN を指定する方法を示します: カタログされた接続について DSN を指定する場合: For pdo_ibm: ibm:DSN=sample;UID=db2inst1;PWD=123 For pdo_odbc: odbc:DSN=sample;UID=db2inst1;PWD=123 カタログされていない接続について DSN を指定する場合: For pdo_ibm: ibm:DSN={IBM DB2 ODBC DRIVER};HOSTNAME=localhost;PORT=50000;DATABASE=sample;PROTOCOL=TCPIP;UI D=db2inst1;PWD=123; For pdo_odbc: odbc:DSN={IBM DB2 ODBC DRIVER};HOSTNAME=localhost;PORT=50000;DATABASE=sample;PROTOCOL=TCPIP;UI D=db2inst1;PWD=123; 第 8 章 – PHP によるアプリケーション開発 303 カタログされた方法で接続する例は以下のリスト8.14で示します: <?php try { /* Use one of the following connection string */ /* For PDO_IBM */ $constrng = 'ibm:DSN=sample;UID=db2inst1;PWD=123'; /* for PDO_ODBC */ $constrng = 'odbc:DSN=sample;UID=db2inst1;PWD=123'; $dbh = new PDO($constrng); echo 'Connected'; } catch (PDOexception $exp) { echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.14 カタログされた方法でデータベースに接続する リスト8.14において、new PDO()メソッドは新規接続を確立します。 非カタログ化接続を使ってデータベースに接続するプログラムを作成するには、セクション 8.3.2.2.2以前に議論されたのと同じ技法を使ってください。 PDOプログラムにDSN名を与える方法は3つあります: コンストラクターに変数として与える この方法を使うと、DSN は文字列としてプログラムに与えられます。しかし、この方法はプ ログラムをデータベース依存にします。データベースロケーションあるいはパスワードが変 更になった場合、このデータベースを参照する全てのプログラムにおいて、対応するエント リーを変更しなければなりません。リスト 8.15 はこの方法を使った例を示します。 <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; try { $dbh = new PDO($constrng, '', ''); echo 'Connected'; } catch (PDOexception $exp) { echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.15 コンストラクターへパラメーターとして DSN を与える 304 DB2 アプリケーション開発入門 ファイルに記述する この方法を使うと、DSN はファイル内で与えられファイルはプログラム内で参照されます。 DSN 変数の値が変わった場合、そのファイルのみ変更する必要があります。DSN が代わ るたびにプログラムを変更する必要がありません。例えば、以下のリスト 8.16 は dsnfile と いう名前のファイルを作成し/usr/local ディレクトリーに保存したと仮定した場合の例です。 <?php $constrng = 'uri:file:///usr/local/dsnfile'; try { $dbh = new PDO($constrng, '', ''); echo 'Connected'; } catch (PDOexception $exp) { echo 'Exception: ' . $exp->getMessage(); }?> リスト 8.16 ファイルを作成し保管する php.ini ファイルの別名を使用する ibm_db2 拡張と同様に、PDO_IBM/PDO_ODBC でも永続および非永続接続を 使うことができます。pdo_odbc.connection_pooling を strict あるいは relaxed で設定し て接続プーリングを有効にしている場合、PDO は接続プールのために ODBC 層へ接続 を開放しないため、永続接続を作成すべきではありません。永続接続上で接続プールを 使用することが望ましいでしょう。非永続接続を作成するには、PDO インスタンスを DSN、 ユーザー名、パスワードを使って以下のリスト 8.17 のように作成します。 <?php /* Use one of the following connection strings */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; try { $dbh = new PDO($constrng, 'db2inst1', '123'); echo 'Connected'; } catch (PDOexception $exp) { echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.17 非永続接続を作成する 永続接続を作成するには、以下のnew PDOフォーマットを使用します: $dbh = new PDO($constrng, 'db2inst1', '123', array(PDO::ATTR_PERSISTENT=> true)); 8.3.3.3 ステートメントを準備・実行する 第 8 章 – PHP によるアプリケーション開発 305 SQL 文を準備・実行する前に、トランザクションの以下の特性を決定します: 使用するカーソル・タイプ エラーのキャッチ方法 使用する分離タイプ 8.3.3.3.1 使用するカーソル・タイプ ibm_db2拡張のように、PDOも2種類のカーソルをサポートします: フォワードのみカーソル このカーソルは PDO ドライバーでデフォルトのカーソルです。利用可能なカーソルのうち最速のカ ーソルとなります。全ての行を取り出した後別の照会を実行する前に、 PDOStatement::closeCursor メ ソ ッ ド を 使 っ て カ ー ソ ル を 必 ず ク ロ ー ズ し て く だ さ い 。 PDOStatement::prepare メソッドで PDO::ATTR_CURSOR を PDO::CURSOR_FWDONLY にセットすることでフォワードのみカーソルを設定することができます。リスト 8.20 はその例を示しま す。 $sql = "SELECT c_id, c_name, c_email FROM customer WHERE c_name = :name"; try { $sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR, PDO::CURSOR_FWDONLY)); $sth->execute(array(':name' => 'Myname')); print_r($sth->fetchAll()); } catch (PDOexception $exp) { echo 'Exception: ' . $exp->getMessage(); } リスト 8.20 フォワードのみカーソルを使う スクロール可能カーソル スクロール可能カーソルはPDO::ATTR_CURSORをPDO::CURSOR_SCROLLにセットするこ とで指定できます。リスト8.21はその例を示します。 $sql = "SELECT c_id, c_email FROM customer WHERE c_name = :name"; try { $sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR, PDO::CURSOR_SCROLL)); $sth->execute(array(':name' => 'Daniel')); while ($row = $sth->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT)) { $data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n"; echo $data; } $sth->closeCursor(); 306 DB2 アプリケーション開発入門 } catch (PDOexception $exp) { echo 'Exception: ' . $exp->getMessage(); } リスト 8.21 スクロール可能カーソルを使う 8.3.3.3.2 PDO でのエラーのキャッチ PDO は例外をキャッチし詳細を表示する例外ハンドラーを持っています。このハンドラーは他のプ ログラミング言語と同様の“try and catch”の構造を持っています。 PDO プ ロ グ ラ ム で 例 外 が 発 生 し た 場 合 、 PDOException イ ン ス タ ン ス が 作 成 さ れ ま す 。 PDOException クラスは Exception クラスの拡張で、3 つのオペレーションモードがあります。 PDO 属性 PDO::ATTR_ERRMODE を設定することで、エラー処理モードが強制設定されます。 表 8.2 はとり得る値を記述します: 値 説明 PDO::ERRMODE_SILENT これは PDO におけるエラー処理のデフォルト モードです。エラーが起こった場合に、対応す るエラー・コードおよびメッセージがステートメン ト・オブジェクト(PDOStatement)とデータベー スオブジェクト(PDO)の両方にセットされます。 このモードを使っているステートメントについて は、エラーはキャッチされず関数が失敗した後 に次のステートメントが実行されます。 PDO::ERRMODE_WARNING PDO アプリケーションを開発あるいはテストして いる場合にこのモードは便利です。エラー・コー ドとメッセージを設定する と共 に、 E_WARNING 例 外 を あ げ ま す 。 こ の E_WARNING は関数名の前に”@”マークをつ けることで抑制できます。 PDO::ERRMODE_EXCEPTION PDO プログラムでエラーを処理するのに最も適 した方法です。エラーが発生した後、その try ブロックで後の関数の実行を妨げる例外がスロ ーされます。制御は例外が処理される catch ブ ロックに渡され、エラーの情報とスタックトレース が提供されます。 表 8.2 PDO::ATTR_ERRMODE パラメーターでセットされるエラー処理モード 以下のリスト 8.18 はエラー処理モードを PDO::ERRMODE_EXCEPTION に設定し、try および catch ブロックで例外を処理する方法の例を示します。プログラムは意図的にテーブルに存在しな い列を使った誤った SQL 文を発行しています。エラーが発生した際に PDOexception がスロー され、getMessage()メソッドを使って例外オブジェクトの詳細が表示されます。 第 8 章 – PHP によるアプリケーション開発 307 <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; $dbh = new PDO($constrng, 'db2inst1', '123'); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "SELECT c_id FROM customer WHERE notexistingcol = :name "; $sth = $dbh->prepare($sql); try { $sth->execute(array(':name' => 'ABC)); $row = $sth->fetchAll(); print_r($row); $sth->closeCursor(); } catch (PDOexception $exp) { echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.18 PDO::ERRMODE_EXCEPTION を使った例外処理 例外が生成された際に、getMessage()メソッドは以下のような出力を生成します: Exception : SQLSTATE[42S22]: Column not found: -206 [IBM][CLI Driver][DB2/LINUX] SQL0206N "NOTEXISTINGCOL" is not valid in the context where it is used. SQLSTATE=42703 (SQLExecute[206] at /root/Desktop/php-5.1.2/ext/pdo_odbc/odbc_stmt.c:133) エラーに関するより詳細な情報を得るには、errorCode()および errorInfo()メソッドを使用できま す: PDO::errorCode()メソッドはエラーの SQLSTATE に関する情報を提供します。 PDO::errorInfo()は SQLSTATE, SQLCODE およびデータベース・サーバーからのエラーメッセ ージといった、エラーに関する全ての情報を提供します。 8.3.3.3.3 使用する分離レベル PDO_IBM/PDO_ODBC を使った PHP アプリケーションでどの分離レベルを使うべきかの考慮点 は、以前 ibm_db2 拡張を使う際に記述した内容と同じです。 8.3.3.3.4 SQL 文を準備・実行する PDO は SQL 文の準備・実行を一ステップで行う方法、あるいは別々に行う方法も提供しています。 SQL 文の準備・実行を一ステップで行う 308 DB2 アプリケーション開発入門 通常、同じプログラム内で繰り返し実行されない SQL 文を実行するにはこのメソッドを使用します。 SQL 文には 2 種類あります: 結果セットを返す SQL 文 PDO::query 関数は列位置と列名で索引付けされた結果セットを返す SQL 文を準備・実 行するのに使用されます。リスト 8.19 はこの query 関数の例です。照会文によって返され た結果セット内の各行が $row という名前の配列に格納され、その値が表示される方法を 見ることができます: <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; $dbh = new PDO($constrng, 'db2inst1', '123'); $sql = 'SELECT c_id, c_name FROM customer'; try { foreach ($dbh->query($sql) as $row) { echo $row[0] . ' ' . $row['C_NAME']; } } catch (PDOexception $exp) { print_r($sth->errorInfo()); echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.19 結果セットを返す SQL を準備・実行する 結果セットを返さない SQL 文 PDO では、結果セットを返さない SQL 文の準備と実行については異なる方法を用いてい ます。PDO::exec はこのタイプの SQL 文に使われ、この関数で影響される行数を返しま す。DELETE, INSERT, あるいは UPDATE といった SQL 文は PDO::exec を使って実 行され、この関数はその影響を受けた行数を返します。 <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; $dbh = new PDO($constrng, 'db2inst1', '123'); $num = $dbh->exec("INSERT INTO customer (c_name, c_email) VALUES ('Piotr', '[email protected]')"); echo 'Number of rows affected is: ' . $num; 第 8 章 – PHP によるアプリケーション開発 309 ?> リスト 8.20 結果セットを返さない SQL 文を準備・実行する SQL 文の準備と実行を別々のステップで行う 同じ SQL 文を何度も異なるパラメーターで実行する予定がある場合、一度準備して複数回実行 することが望ましいでしょう。この方法はパフォーマンスのためにも、また準備と実行を組み合わせ た場合と比べて、新たなパラメーターがデータベースに対してバインドされるたびにデータ型を確 認するので SQL インジェクションのような状況を避けるためにも、より安全な方法として推奨されま す。 PDOでは、パラメーター・マーカーは2種類に分類されます: 名前つきパラメーター・マーカー パラメーター名の先頭に”:”をつけることで、パラメーター・マーカーに名前を与えることがで きます。このパラメーター・マーカーの値は SQL にバインドされ、完了後実行されます。 名前なしパラメーター・マーカー DB2 がこのパラメーター・マーカーの値は追ってバインドされることを理解できるように、 SQL 文で?シンボルが使われます。 同じ SQL 文内で、名前つきあるいは名前なしパラメーター・マーカーの両方を使うことはできませ ん。SQL 文の準備と実行には以下の 3 つのステップがあります: 1. SQL 文を準備する PDO のPDO::prepare 関数はSQL文をパラメーター・マーカー有り無しのいずれの場合も準備 するのに使われます。この関数ではオプションを使ってドライバーオプションを使ってどのカーソ ルを使うか選択します。そのオプションは追ってsetAttributeメソッドを使って設定することもでき ます。例えば、準備中にカーソルをスクロール可能にセットするには、以下の文が使用できます: $sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR, PDO::CURSOR_SCROLL)); PDO_IBM/PDO_ODBC におけるデフォルト・カーソルはフォワードのみカーソルです。カーソルを ス ク ロ ー ル 可 能 に セ ッ ト し た 場 合 は 、 PDO::ATTR_CURSOR 属 性 を PDO::CURSOR_FWDONLY に設定することでフォワードのみカーソルに戻すことができます。 2. パラメーターをバインドする SQL 文にパラメーターをバインドする方法は 2 つあります: バインド関数を使う PDOStatement::bindParam あるいは PDOStatement::bindValue をこのタスクに使用するこ とができます。これらの 2 つのメソッドは PDO::prepare を使って SQL 文を準備した後に PDOstatement インスタンスのために呼び出されます。この関数を使ってバインドされるデータ型 を指定する必要があります。指定するデータ型は以下の通りです: 310 DB2 アプリケーション開発入門 整数データ型には PDO::PARAM_INT 文字列データ型には PDO::PARAM_STR ラージ・オブジェクトには PDO::PARAM_LOB null 値をバインドするには PDO::PARAM_NULL リスト8.21は名前つきパラメーター・マーカーと共にbindParamとbindValuesをどのように使うかを 示します: <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; $dbh = new PDO($constrng, '', ''); $cid = 100; $name = 'ABC'; $sql = "SELECT c_id, c_name FROM customer WHERE c_id > :id AND c_name NOT LIKE :name"; $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try { $sth = $dbh->prepare($sql); $sth->bindValue(':id', $cid, PDO::PARAM_INT); $sth->bindParam(':name', $name, PDO::PARAM_STR, 10); $sth->execute(); $result = $sth->fetchAll(); print_r ($result); } catch (PDOexception $exp) { print_r($sth->errorInfo()); echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.21 bind 関数を使う PDOStatement::bindParaを使ってバインドされるパラメーターの長さを強制する追加の変数を 持つこともできます。 変数の値を配列で渡してバインドする リスト 8.22 は PDO プログラムで名前なしパラメーターを使う例を示します: <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; 第 8 章 – PHP によるアプリケーション開発 311 /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; $dbh = new PDO($constrng, '', ''); $cid = 100; $name = 'ABC'; $sql = "SELECT c_id, c_name FROM customer WHERE c_id > ? AND c_name NOT LIKE ?"; $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try { $sth = $dbh->prepare($sql); $rc = $sth->bindValue(1, $cid, PDO::PARAM_INT); $rc = $sth->bindParam(2, $name, PDO::PARAM_STR, 10); $rc = $sth->execute(); $result = $sth->fetchAll(); print_r($result); } catch (PDOexception $exp) { print_r($sth->errorInfo()); echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.22 変数を配列に入れて渡してバインドする 3. SQL 文を実行する PDOStatement::execute は準備された SQL 文を実行するのに使用されます。変数はバインド 関数を使ってバインドするか、あるいは SQL 文は実行と共に配列として変数を渡すことでバインド されます。リスト 8.23 は名前つきパラメーター・マーカーを実行する関数で使う方法を示します: <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; $dbh = new PDO($constrng, '', ''); $id = 10; $sql = "select c_name from customer where c_id > :id"; $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try { $sth = $dbh->prepare($sql); $rc = $sth->execute(array(':id' => $id)); $result = $sth->fetchAll(); print_r($result); 312 DB2 アプリケーション開発入門 } catch (PDOexception $exp) { print_r($sth->errorInfo()); echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.23 名前つきパラメーター・マーカーを PDOStatement::execute で使う 8.3.3.3.5 ストアード・プロシージャーを作成・呼び出す PDO と PHP を使って他の SQL 文を実行するのと同様に SQL ストアード・プロシージャーを作成 することができます。しかし、クライアントからストアード・プロシージャーを呼ぶ必要がある場合、そ のタイプ毎にパラメーターのバインド方法を考慮しなければなりません。ストアード・プロシージャー には IN,OUT,INOUT の 3 つの変数のタイプがあります。バインドのパラメーターにおいて、データ 型定数と変数はビット OR 演算子(|)で結合されます。変数型 PDO::PARAM_INPUT_OUTPUT は OUT および INOUT 変数に使われます。IN 変数には、変数型は必要ありません。リスト 8.24 は全ての変数型を使って結果セットを返すストアード・プロシージャーを示します。ストアード・プロ シージャーが実行された後、ストアード・プロシージャーのパラメーター・マーカーとバインドされた 変数にストアード・プロシージャーの実行結果の値が代入されます。 <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; $dbh = new PDO($constrng, 'db2inst1', '123'); $id = 10; $sql = 'CALL getdetails(?, ?, ?)'; $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $amount = 0; $c_id = 140; $quantity = 100; try { $sth = $dbh->prepare($sql); // Input parameter $sth->bindParam(1, $c_id, PDO::PARAM_INT); // Output parameter $sth->bindParam(2, $amount, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT); // Input output parameter $sth->bindParam(3, $quant, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT); $sth->execute(); echo 'The INOUT parameter is: ' . $quant . ' and the OUT parameter is: ' . $amount; 第 8 章 – PHP によるアプリケーション開発 313 $rowset = $sth->fetchAll(PDO::FETCH_NUM); print_r($rowset); } catch (PDOexception $exp) { print_r($sth->errorInfo()); echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.24 PDO_IBM/PDO_ODBC を使って PHP でストアード・プロシージャーを呼ぶ 8.3.3.3.6 トランザクションを処理する PDO はデフォルトでは autocommit モードで実行されます。つまり、全ての照会文は(成功した 場合)コミットあるいは(失敗した場合)ロールバックされます。PDO::beginTransaction などのメソ ッドを複数の SQL 文をひとつのトランザクションの一部として実行するために使うことができます。 この関数は PDO アプリケーションの autocommit モードをオフにします。トランザクションが完了 した後、PDO::commit 関数を使ってコミットするか、あるいは PDO::rollback 関数を使ってロー ルバックすることができます。 リスト 8.25 は DB2_PDO_IBM あるいは PDO_ODBC を使った PHP でのトランザクションの扱い 方を示します。エラーが発生した際に、PDO::ERRMODE_EXCEPTION をエラー処理モードとし て設定した例外処理が行われています。キャッチ節では、トランザクションはロールバックされ、エラ ーが表示されます。エラーが発生しなかった場合、トランザクションはコミットされ完了します。 <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; $dbh = new PDO($constrng, 'db2inst1', '123'); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try { $dbh->beginTransaction(); $dbh->exec(" INSERT INTO customer (c_name, c_email) VALUES ('ABC', '[email protected]') "); $dbh->exec(" INSERT INTO customer (c_name, c_email) VALUES ('DEF', '[email protected]') "); $dbh->exec(" INSERT INTO customer (c_name, c_email) VALUES ('GHI', '[email protected]') "); $dbh->commit(); 314 DB2 アプリケーション開発入門 } catch (PDOexception $exp) { print 'Rolling back transaction'; $dbh->rollback(); print_r($dbh->errorInfo()); echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.25 PHP での IBM_PDO/PDO_O 8.3.3.4 結果を処理する PDO はデータを取り出す二つの方法を提供しています: 1. バッファー取り出し バッファー取り出しでは SQL 文で返された結果セットの全ての行をはいれつに取り出すことができ ます。大きな結果セットを返す SQL 文の場合、システム・リソースを大量に消費するためこのメソッ ドの使用は推奨されません。 2. バッファーなし取り出し PDOstatement::fetch を使って、各行を一回毎に取り出し結果セットを操作することができます。 PDOstatement::fetch には異なるデータの列を取り出す異なるオプションがあります。以下のセ クションではそのオプションについて記述しています。 FETCH_BOUND と bindColumn を使う この方法では、結果セットで返された各列を変数に割り当てることができます。 PDOStatement::fetch を実行後、バインドされた各変数の対応するちは結果セットの値に更新さ れます。 PDO::FETCH_BOUND 定数はバインドされた列変数が取り出し関数によって操作でき るようにする、フェッチのためのパラメーターです。リスト 8.26 はバインドされた列のフェッチ例を示 します。 <?php /* Use one of the following connection string */ /* The connection below is for pdo_ibm */ $constring = 'ibm:sample'; /* The connection below is for pdo_odbc */ $constring = 'odbc:sample'; $dbh = new PDO($constrng, '', ''); $id = 10; $sql = "select c_id, c_name from customer where c_id > :id"; $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try { $sth = $dbh->prepare($sql); $sth->execute(array(':id' => $id)); $sth->bindColumn(1, $id); $sth->bindColumn(2, $name); 第 8 章 – PHP によるアプリケーション開発 315 while ($row = $sth->fetch(PDO::FETCH_BOUND)) { echo 'id is: ' . $id . ' and name is: ' . $name; } } catch (PDOexception $exp) { print_r($sth->errorInfo()); echo 'Exception: ' . $exp->getMessage(); } ?> リスト 8.26 FETCH_BOUND を使ってデータを取り出す 取り出し関数をパラメーターなしで使う これはデフォルトのオプションです。取り出し関数は位置付けされた列と共に、結果セットの各行を 返します。リスト 8.27 はその例を示します。 while ($row = $sth->fetch()) { echo 'id is: ' . $row[0] . ' and name is: ' . $row[1]; } リスト 8.27 Fetch 関数を使った例 FETCH_ASSOC を使う 照会文によって返された結果セットの行を結果セットの列名と共に配列に取り出すことができます。 リスト 8.28 はその例を示します。 while ($row = $sth->fetch(PDO::FETCH_ASSOC)) { echo 'id is: ' . $row['C_ID'] . ' and name is: ' . $row['C_NAME']; } リスト 8.28 Fetch_Assoc 関数を使った例 FETCH_BOTHを使う PDO::FETCH_BOTH 変数を PDOStatement::fetch 関数に渡した場合、列名と位置情報と共 に各列を返します。リスト8.29 はその例を示します。 while ( $row = $sth->fetch(PDO::FETCH_BOTH)) { echo 'id is: ' . $row[0] . ' and name is: ' . $row['C_NAME']; } リスト 8.29 Fetch_Both を使った例 スクロール可能カーソルを使う スクロール可能カーソルを使っていてそのカーソルを結果セットから次の行を取り出すために PDO::FETCH_ORI_NEXT 定数を渡した場合、カーソルをスクロールすることができます。 リスト 8.30 はその例を示します。 $sql = "SELECT * FROM customer"; try { 316 DB2 アプリケーション開発入門 $offset = 0; $sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR, PDO::CURSOR_SCROLL)); $sth->execute(); while ($row = $sth->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT)) { $data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n"; echo $data; } $sth->closeCursor(); } catch (PDOexception $exp) { print_r($sth->errorInfo()); echo 'Exception: ' . $exp->getMessage(); } リスト 8.30 スクロール可能カーソルを使う オブジェクトへの取り出しを使う PDO::FETCH_LAZY 定数とPDO::FETCH_OBJ 定数を与えることで、データをオブジェクトに 直接取り出すことができます。PDO::FETCH_LAZY 定数では、列にアクセスするのに使われるオ ブジェクト変数名が同じ名前で作成されます。列は列名あるいは位置番号で参照することができま す。リスト8.31 はその例を示します。 while ($row = $sth->fetch(PDO::FETCH_LAZY)) { print_r($row->C_NAME); } while ($row = $sth->fetch(PDO::FETCH_OBJ)) { print_r($row->C_NAME); } リスト 8.31 列参照に Fetch を使う 8.3.3.5 リソースを開放する ステートメントリソースを再利用できるようにするために、フェッチ終了後毎回カーソルをクローズす る必要があります。カーソルをクローズするのに使うメソッドは PDOStatement::closeCursor で す。接続リソースはnull値を割り当てることで開放されます。リスト8.32 はその例を示します。 // Connect to the database, use one of the following // for PDO_IBM $dbh = new PDO('ibm:sample', '', ''); // for PDO_ODBC $dbh = new PDO('odbc:sample', '', ''); // Perform database operations here ... // Free the connection $dbh = null; リスト 8.32 接続リソースを開放する 第 8 章 – PHP によるアプリケーション開発 317 8.4 PHP と DB2 の最適化 PHP アプリケーションが動作した後、最善のパフォーマンスを得るためにアプリケーションと DB2 の両方をチューニングできます。DB2 はあなたの書いた SQL が環境ごとに最適の方法で実行さ れる効果的なコストベースのオプティマイザーを使っています。 8.4.1 PHP-DB2 でパフォーマンスを向上するデザイン上の考慮点 アプリケーションをデザイン・コーディングする際には以下の点を考慮する必要があります: 繰り返し実行される SQL 文には prepare と execute メソッドを実行します。 PDO ドライバーを使う場合、そして ibm_db2 ドライバーで永続接続を使う場合にはコネク ション・プーリングを使用します。あるいは、DB2 側で接続コンセントレーターを使用します。 ロジック上実行できるだけコミットを頻繁に実行します。コミットを実行することでロックを開 放し、並列実行性を実現できます。 ネットワーク・トラフィックや計算リソースを減らすために、ロジックをできるだけデータベース 層におき、ユーザー定義関数やストアード・プロシージャー、SQL/XML を使用します。 最適なストレージスペースを用意します。大きな表は異なるディスクに配置された表スペー スに置き、DB2 ログは異なるディスクに保管します。 DB2 デザイン・アドバイザーを使って列の索引を効果的に作成します。 設定アドバイザーウィザードを使って、あなたの DB2 環境を最適化してデータベースとデ ータベース・マネージャーの設定を変更します。 システムカタログと共に全ての表について定期的に RUNSTATS を実行します。 可能なら使用可能なメモリーの 75%を使ってバッファープールを構成します。 DB2 の活動をモニターするためにモニターツールを使います。 アプリケーションのデータ整合性要件を維持する、最低限・限定的な分離レベルを使いま す。 8.5 演習 この演習では、SAMPLE データベースのデータにアクセスする小さな PHP スクリプトを書きます。 演習を実行する前に、サーバーにインスタンス・オーナー(例えば linux では db2inst1、Windows では db2admin)としてログインし、以下を実行します。 1. 以前に実行していなければ、SAMPLE データベースを作成するために db2sampl コマ ンドを実行します。 2. EMPLOYEE テーブルにデータを挿入・フェッチする PHP スクリプトを書きます。 318 DB2 アプリケーション開発入門 3. PHP スクリプトを Apache web サーバーで実行するために、Windows では PHP ファイ ル db2employee.php を C:/Program Files/Apache Group/Apache2/htdocs ディレクト リーにコピーします。 4. この練習問題のサンプル・スクリプトとして db2employee.php がこの本に付属していま す。ユーザーID,パスワード、ホスト名を適宜修正し、Web ブラウザーで http://localhost/db2employee.php を指定して PHP スクリプトを実行することができます。 8.6 まとめ この章では、DB2 と動作させるための PHP アプリケーション環境の構築方法について学習しまし た。Ibm_db2 拡張の使い方や pdo_ibm/pdo_odbc ドライバーの準備と PHP を通じた DB2 上で の SQL の準備と実行を含む PHP と DB2 アプリケーション開発についての基本概念を理解したこ とになります。 8.7 確認問題 1. db2_connect と db2_pconnect を使った場合のリソース開放の違いは何か? 2. 接続プーリングとは何か? どのようなときに有利か? 3. Apache HTTP サーバー 2.x において PHP サポートを有効にする方法は? 4. PHP インストールの設定ファイルのパスを決定する方法は? 5. 以前に Unified ODBC で書かれたアプリケーションを ibm_db2 に移植するために必要なステ ップは? 6. ibm_db2 拡張で使われない FETCH メソッドを選択せよ: A. db2_fetch_array B. db2_fetch_assoc C. db2_fetch_both D. db2_fetch_column 7. ibm_db2 とは何か? A. ドライバー B. 拡張モジュール C. アダプター D. データ・オブジェクト E. 上記のいずれでもない 8. PDO を使うストアード・プロシージャーは以下のどのタイプのパラメーターを使用するか? A. INPUT 第 8 章 – PHP によるアプリケーション開発 319 B. OUTPUT C. EXECUTE D. INOUT E. 上記のいずれでもない 9. 以下のどのファイルが PHP の設定詳細を含んでいるか? A. httpd.conf B. php_conf C. php.ini D. httpd.ini E. 上記のいずれでもない 10. セキュリティーとパフォーマンスの観点から SQL 文を実行する最善の方法は以下のいずれ か? A. 準備して実行する B. 実行する C. 準備する D. 準備と実行を同時に行う E. 上記のいずれでもない 9 第 9 章 Perl によるアプリケーション開発 Perl (Practical Extraction and Reporting Language) は Windows や Linux, Unix、そして Mac OS X などの多くの OS で利用可能な、プラットフォームに依存しないスクリプト言語です。オープ ン・ソース言語なので、Perl のインタープリターはソース・コードでも実行可能形式でも無償でダウ ンロード可能です。 例えば、正規表現を強くサポートしているといった強力なテキスト処理機能を備えているため、Perl はレポートを生成するアプリケーションだけでなく、スタンドアロンないしは Web ベースのデータベ ース・アプリケーションまで広く用いられます。Perl スクリプトを用いて、動的 SQL 照会を生成したり、 返されたデータをフェッチしたり処理したりする事が容易に可能です。 本章では以下についてご説明します。 DB2 用の Perl 環境の構築 Perl アプリケーションから DB2 データベースへの接続 DB2 データにアクセスする Perl アプリケーションの開発 注: もし Perl プログラム言語が初めての場合、本書のシリーズの一つである ebook「Getting Started with Perl」を参照ください。 9.1 Perl – DB2 間のアプリケーション:全体像 Perl アプリケーションは、DB2 を含むほとんどの関係型データベースへのアクセスに Perl Database Interface (DBI) を用います。Perl DBI は、Perl アプリケーションから異なるデータベー スに対して、同じシンタックスで、それぞれの特定のデータベースの詳細を意識せずにアクセス可 能にする、業界標準のアプリケーション・プログラミング・インターフェース(API)です。これらの詳細 は、Perl DBI をサポートするデータベース・ベンダーによって提供されている下位層の Database Driver (DBD)によって管理されています。 図 9.1 は、Perl スクリプトがどのように DBI モジュールと DBD ドライバーを通じて複数のデータベ ースへのアクセスするのかについいて図解しています。 322 DB2 アプリケーション開発入門 図 9.1 DBI モジュールと DBD ドライバーを使った Perl スクリプトのデータベースへのアクセス 図 9.1 に示すように、DBI モジュールは、Perl アプリケーションと 1 つ以上のデータベースドライバ ー・モジュールの間に位置する、データベースに依存しないインターフェースを提供します。アプリ ケーションは、データベースによって提供された下位の DBD ドライバーが実際の作業をしていたと しても、インターフェースだけ知ればよい事になっています。Perl - DB2 間のアプリケーションの場 合、そのドライバーは DB2 データベースにアクセスするための詳細を提供する DBD::DB2 ドライ バーとなります。 Perl DBI モジュールは標準のデータベース・アクセス・インターフェイスを定義しているので、 Oracle といったある DBM へアクセスするための DBI で記述されたアプリケーションを IBM DB2 といった他の DBMS へのアクセスするものへ容易に移植する事ができます。さらに、Perl DBI モ ジュールは ODBC や JDBC インターフェースに非常によく似ているため、DBI で記述されたアプ リケーションを ODBC や JDBC インターフェースに移植する事、そしてその逆も簡単です。 注: Perl DBI の詳細情報は http://dbi.perl.org/ を参照してください。 最新の DBD::DB2 ドライバーおよび関連情報は http://www.ibm.com/software/data/db2/perl/ と http://search.cpan.org/~ibmtordb2/ を参照して下さい。 第 9 章 - Perl によるアプリケーション開発 323 9.2 環境設定 Perl アプリケーションから DB2 データベースにアクセスするためには、DB2 で動作するように Perl の環境を設定する必要があります。次の 3 つの手順が必要です: 1. Perl 言語環境の導入 Perl 5.8 以降を導入する必要があります。Linux / UNIX/ Mac OS X では、Perl は OS 導入の 標準コンポーネントとして通常出荷されています。 Windows では、http://www.activestate.com/activeperl/ から ActiveState の無償のバイナリー 配布物をダウンロードすることができます。 ActivePerl は、Linux/ UNIX 上でも無償で使用可能 です。http://www.activestate.com/activeperl/downloads/からバイナリーをダウンロードできま す。Windows では Windows インストーラーで、Linux/Unix では install.sh を実行して Perl を 導入して下さい。 あるいは、http://dev.perl.org/から Perl インタープリターのソース・コードをダウンロードして、お 使いのプラットホームにあわせて、適切な C コンパイラーで Perl のバイナリーを生成することも 出来ます。Perl ソースの導入やビルドについて、詳しくはこのウェブサイトを参照ください。 導入が完了したら、perl - v を実行して、Perl のバージョンを確認することができます。もしバー ジョンが 5.8 より低い場合は、5.8 以降にアップグレードする必要があります。 2. Perl DBI モジュールの導入 DB2 と DBD::DB2 ドライバー・モジュールを含む RDBMS の前提条件です。 ActivePerl 配布の perl を使用していてインターネットへアクセスできる場合、次のコマンドを発 行することで ActivePerl の Perl Package Manager を介し DBI モジュールのバイナリー/・バー ジョンを導入することができます: ppm install DBI Perl Package Manager は DBI モジュールをダウンロードしそれを自動的に導入します。ある いは、インターネットへのアクセスができるのであれば、以下を実行して DBI モジュールをソース からビルドおよび導入する事が可能です: perl -MCPAN -e "install DBI" 上記のコマンドは DBI のソース・コードをダウンロードした後、ビルドと導入を CPAN モジュール を介して自動的に行います。ソースをビルドするために C コンパイラーが必要であることに注意 してください。 CPAN モジュールの詳細については、 http://www.perl.com/doc/manual/html/lib/CPAN.html を参照してください。 もしインターネットにアクセスできない場合、http://search.cpan.org/〜timb/ DBI から最新リリ ースの Perl DBI モジュールのソース・コードをダウンロードした後、Linux/Unix は以下 リスト 9.1、 Windows は リスト 9.2 に示されるようにソースをビルドして DBI モジュールを導入する事ができ ます。ソースのビルドには C コンパイラーが必要です。 # the source is DBI-<x.xxx>.tar.gz, where x.xxx means version. zcat DBI-<x.xxx>.tar.gz|tar xvf – 324 DB2 アプリケーション開発入門 cd DBI-<x.xxx> perl Makefile.PL make make test make install リスト 9.1 Linx/Unix における DBI モジュールのソースからの導入 #unpack/unzip the source file DBI-<x.xxx>.tar.gz using winzip cd DBI-<x.xxx> perl Makefile.PL nmake nmake test nmake install リスト 9.2 Windows における DBI モジュールのソースからの導入 注: Perl DBI の API に関して詳しくはhttp://search.cpan.org/~timb/DBI/DBI.pm を参照してくださ い。 3. IBM DB2 データ・サーバー・クライアントの導入 上記のソフトウェアの導入の後、Perl DB2 ドライバー DBD::DB2 を導入できます。これについては 次セクションで触れます。 9.2.1 Perl アダプターとドライバー この文書作成時点での DBD::DB2 ドライバー・モジュールの最新リリースは 1.78 です。 DBD::DB2 ドライバーのより詳しい情報はhttp://www.ibm.com/db2/perl/ と http://search.cpan.org/〜ibmtordb2/ を参照下さい。 Windows で Active Perl 配布のものを使用していてインターネットが利用可能であれば、以下のコ マンドによって、DBD::DB2 モジュールを ActivePerl の Perl Package Manager を介して導入す る事が出来ます。 Perl 5.8 の場合: ppm install http://theoryx5.uwinnipeg.ca/ppms/DBD-DB2.ppd Perl 5.10 の場合: ppm install http://cpan.uwinnipeg.ca/PPMPackages/10xx/DBD-DB2.ppd 第 9 章 - Perl によるアプリケーション開発 325 あるいは、ソースをビルドしてドライバーを導入する事ができます。C コンパイラーが必要です。最 新リリースの DBD::DB2 モジュールのソースは http://www.cpan.org/authors/id/I/IB/IBMTORDB2 から導入し、以下リスト 9.3 (Linux/Unix 用) ないしはリスト 9.4 (Windows 用) の手順を実行します。 # the source is DBD-DB2-<x.xx>.tar.gz, where x.xx means version. zcat DBD-DB2-<x.xx>.tar.gz|tar xvf – cd DBD-DB2-<x.xx> export DB2_HOME=/home/db2inst1/sqllib #for example perl Makefile.PL make make test make install リスト 9.1 – Linux/Unix におけるソースからの DBD::DB2 ドライバーの導入 #unpack/unzip the source file DBD-DB2-<x.xx>.tar.gz using winzip cd DBD-DB2-<x.xx> perl Makefile.PL nmake nmake test nmake install リスト 9.2 – Windows におけるソースからの DBD::DB2 ドライバーの導入 9.3 Perl DB2 アプリケーションの開発 このセクションでは、Perl の DBI の API を呼び出して DB2 データにアクセスする Perl のアプリケ ーションを開発する方法について説明します。 9.3.1 DB2 データベースへの接続 最初に、データベースにアクセスするために、標準の DBI API を提供している Pel DBI モジュー ルを Perl に対してロード可能にします。これは次の行をアプリケーションに記述することで可能とな ります。 Use DBI; その後、次の構文を用いて、DBI パッケージの DBI->connect メソッドを呼んで DB2 データベー スに接続します。 $dbhandle = DBI->connect($data_source, $userID, $password, \%attr); 326 DB2 アプリケーション開発入門 表 9.1 は DBI->connect メソッドのパラメーターのいくつかを説明しています。 Name $data_source $userID $password \%attr Description ‘dbi:DB2:dbalias’の形式のデータベース接続の文字列 dbalias は次のいず れかを表します: 1) DB2 クライアントにカタログされた DB2 データベースの別名 または、 2) “DATABASE=database; HOSTNAME=hostname; PORT=port; PROTOCOL=TCPIP; UID=username; PWD=password;”.というフォーマ ットのデータベース名、ホスト名、ポート番号、プロトコル、ユーザーID,やパス ワードを含む接続文字列。これらのフォーマットを利用すると、最初にクライア ントででカタログをすることなしに、直接 TCPIP 経由でリモート・データベース に接続することができます。 データベースへの接続に使われまるユーザーID オプションであり、その場合、 username を接続文字列$data_source にオプションで指定します。 ユーザーID がデータベースに接続すために使われるパスワード。オプション であり、その場合 password を接続文字列$data_source にオプションで指定 します。 オプションです。データベース接続の属性のリストへの参照。 表 9.1 DBI->connect メソッドのパラメーター DBI の-> connect メソッドは、それが事前にロードされていなければ、DBD::DB2 モジュールを自 動的にロードし、接続に成功した場合にはデータベース・ハンドルを返します。データベース・ハン ドルはデータベース接続について、以降の全てのすべての機能のために使用されるハンドルです。 リスト 9.5 に示されているのは SAMPLE データベースへの接続を確立する例です。 Use DBI; my $dbhandle = DBI->connect("dbi:DB2:sample", "db2admin", "password", {AutoCommit=>0}); リスト 9.5 – クライアントでカタログされた sample データベースへの接続 上記のリストでは、データベースユーザーID は db2admin でパスワードは password、そして AutoCommit の接続属性はオフになっています、これはオフに設定された事を意味します。これ は明示的にこの接続に対して、トランザクションのコミットまたはロールバックを発行できることを意 味します。AutoCommit はデフォルトではオンです。正常に実行された後は、DBI->connect メソッ ドは、$dbhandle 変数にデータベース・ハンドルを戻します。 もし SAMPLE データベースがそのインスタンスがポート 50000 番を Listen しておりクライアントで まだカタログされていない host2 のマシンにあるリモート・データベースであれば、リスト 9.6 に示す ように、TCP / IP 経由で直接の接続を行う事ができます。 use DBI; 第 9 章 - Perl によるアプリケーション開発 327 my $dbhandle = DBI->connect("dbi:DB2:DATABASE=sample; HOSTNAME=host2; PORT=50000; PROTOCOL=TCPIP;UID=db2admin;PWD=password", {AutoCommit=>0}); リスト 9.6 - リモートの SAMPLE データベースに直接 TCP/IP 経由で接続する 9.3.2 データの抽出 データベースに接続したら、データベースからデータを抽出する SQL の SELECT ステートメント を発行することができます。 アプリケーション作成時に SELECT ステートメントが確定していない場合、変数入力やパラメータ ー・マーカーを含む SQL の実行方法を説明している 9.3.4 節 を参照してください。 SELECT ステートメントが確定している場合は、次の手順に従ってください: 1. DBI->connect メソッドを呼び出してデータベースに接続します。 2. データベース・ハンドルの prepare メソッドを呼び出して、SELECT SQL ステートメントを準備し ます。prepare メソッドは SQL の準備に成功するとステートメント・ハンドルを戻します。例えば、次 のように文字列引数として渡される SELECT ステートメントを使用して prepare メソッドを呼び出す ことができます: $sthandle = $dbhandle->prepare( "SELECT firstnme, lastname FROM employee WHERE workdept='A00'" ); 補足: $ dbhandle は手順1で戻したデータベース・ハンドルで、$dbhandle->prepare メソッドは SQL の 準備に成功した場合、$sthandle にステートメント・ハンドルを戻します。 3. ステートメント・ハンドルを使って execute メソッドを呼び出すことにより、事前準備済みの SELECT ステートメントを実行します。SQL ステートメントの実行に成功すると、ステートメント・ハン ドルは結果セットに関連付けられます。 例えば、前のステップで準備されたステートメントを以下の Perl ステートメントによって実行すること が出来ます。 $rc = $sthandle->execute(); 4. ステートメント・ハンドルの fetchrow_array() メソッドを呼び出して、ステートメント・ハンドルと関 連付けられた結果セットから行をフェッチします。このメソッドは各列に 1 つの値を持つ行を配列と して返します。 例えば、リスト 9.7 に示すようにステートメント・ハンドル$stthandle から行をフェッチできます。 while (($firstnme, $lastname) = $sthandle->fetchrow_array()) { print "$firstnme $lastname\n"; 328 DB2 アプリケーション開発入門 } リスト 9.7 – 結果トセットからの行のフェッチ 注: Fetchrow_array に加えて、結果セットからの行フェッチで柔軟な方法をサポートするため、ステ ートメント・ハンドルは fetchrow_arrayref, fetchrow_hashref, fetchall_arrayref, fetchall_hashref といった他の多くの方法を提供しています。これらの関数についての詳細情報 はhttp://search.cpan.org/~timb/DBI/DBI.pm.を参照して下さい。 上記のコードの記述部分は、本書に付随しているファイル Exercise_Files_DB2_Application_Development.zip に含まれているスクリプト select.pl の一部 です。スクリプトのユーザーIDやパスワード部分を適宜編集する事でコードをテストする事が可能 です。: perl select.pl このスクリプトの実行結果は図 9.2 に表示されています。 図 9.2 – select.pl の実行 9.3.3 データの挿入・更新・削除 INSERT/UPDATE/DELETE の各 SQL ステートメントを発行する際、アプリケーション作成時に予 めわかっているのであれば、アプリケーション・データベース・ハンドルの do() メソッドを呼び出せ ます。それ以外の場合で、変数入力やパラメーター・マーカーを含む SQL ステートメントを実行す るには、9.3.4 節 を参照してください。 do()メソッドの構文は以下です。 $cnt = $dbh->do($statement); do()メソッドのパラメーターの詳細は表 9.2 に記載されています。 第 9 章 - Perl によるアプリケーション開発 Name Description $statement ステートメント文字列 329 SQL ステートメントまたは undef エラーの影響を受けた行の数。 戻り値 -1 は、 行数が不明か範囲外か、ないしは利用不可能である事を意味します。 表 9.2 データベース・ハンドルの do()メソッドのパラメーター $cnt リスト 9.8 は do()メソッドで ISERT/UPDATE/DELETE の各ステートメントを発行する方法と、同様 に CREATE/DROP TABLE DDL を実行する方法も記述しているいくつかの例です。 (1) $cnt = $dbhandle->do (“CREATE TABLE product(product_id CHAR(6), name CHAR(30))"); (2) $cnt = $dbhandle->do ("INSERT INTO product VALUES ('000001','computer'),('000002',’TV’)") (3) print "Returns for insert: $cnt \n"; (4) $cnt = $dbhandle->do ("UPDATE product SET name = 'notebook' WHERE product_id='000001'"); (5) print "Returns for update: $cnt \n"; (6) $cnt = $dbhandle->do ("DELETE FROM product WHERE product_id='000003'"); (7) print "Returns for delete: $cnt \n"; (8) $cnt = $dbhandle->do ("DROP TABLE product"); リスト 9.8 – INSERT/UPDATE/DELETE ステートメントの実行 リスト 9.8 の各項目は以下のとおりです。 (1) $dbhandle->do メソッドを呼び出して product 表を作成します。 (2) $dbhandle->do メソッドを呼び出して product 表に行を挿入します。 (3) 挿入された行数を表示します。 (4) $dbhandle->do メソッドを呼び出して表の行を更新します。 (5) 更新された行数を表示します。 (6) 表からいくつかの行を削除します。 (7) 削除された行数を表示します。 (8) 表をドロップします。 上記のコード例は、本書に添付されている ins_upd_del.pl の一部です。スクリプトのユーザーID やパスワードを適切に編集すればコードをテストする事ができ、以下のように実行する事ができま す。 perl ins_upd_del.pl 330 DB2 アプリケーション開発入門 以下の図 9.3 は Ins_upd_del.pl の実行結果です。 図 9.3 ins_upd_del.pl の実行 9.3.4 パラメーター・マーカーでの SQL ステートメント実行 この節では、パラメーター・マーカーまたは変数の入力を含む SQL ステートメントをどのように発行 するかを説明します。SQL ステートメントのパラメーター・マーカーは疑問符文字「?」ないしは、変 数名の接頭部にコロン「:」が付きます。 パラメーター・マーカーを含む SQL ステートメントの実行は以下のようにします。 1 DBI->onnect メソッドを呼び出して、データベースに接続します。 2 prepare メソッドを呼び出して、ステートメントの準備をします。準備が正常終了すればステート メント・ハンドルが戻されます。例えば、パラメーター・マーカーを含む SELECT ステートメント は以下のように準備できます。 $sthandle = $dbhandle->prepare( 'SELECT empno, lastname, job, salary FROM employee WHERE workdept = ?' ); 上記の SELECT ステートメントはパラメーター・マーカー ”?” を述部の”wrokdept = ?” に含 んでいますが、これは SQL が実行されるまでわからない部門番号の変数の入力を意味しま す。 SQL ステートメントが正常に準備されると、prepare メソッドはステートメント・ハンドルを 変数$ sthandle に返します。 3 ステートメント・ハンドルを bind_param メソッドを呼び出して、ローカルの Perl 変数にパラメー ターを関連付けます。Bind_param メソッドの構文は $sth->bind_param($p_num, $bind_value, \%attr) となります。 表 9.3 は bind_param のパラメーター詳細について記述しています。 第 9 章 - Perl によるアプリケーション開発 331 Name Description $p_num パラメーター・マーカーを含む SQL の最初のインデックス位置を指定しま す。 $bind_value パラメーター番号で指定されるパラメーターを関連付けるための Perl 変数 ないしは値。 \%attr オプション:パラメーターの型、精度、スケールを示すあめに用いる事がで きます。 表 9.3 ステートメント・ハンドルの bind_param メソッドのパラメーター 例えば、”A00”という値を準備された SELECT ステートメントに関連付けるために、以下のよう に先述した形で bind_param を呼ぶ事ができます。 $sthandle->bind_param(1,"A00"); 正常に実行されると、”A00”という値は SQL の述部”workdept = ?”のパラーメーター・マーカーに関連 付けられます。 4 このステートメントを実行するために、ステートメント・ハンドルの execute メソッドを呼び出しま す。それが SELECT ステートメントか、結果セットから戻さすストアード・プロシージャーに対す る CALL だった場合(ストアード・プロシージャーの呼び出しは後述の節で詳しく触れます。)、 execute メソッドの呼び出しが成功した後、ステートメント・ハンドルが結果セットと関連付けら れます。その後、結果セットから行を取得するために、前の 9.3.2 節で説明した fetchrow_array()といった関数を用いる事ができます。 たとえば、次のように上記の SELECT ステートメントを実行することができます: $sthandle-> execute(); SQL ステートメントの実行が成功した後は結果セットがステートメントに関連付けされているの で、結果セットから行のフェッチを開始することができます。 上記のコード例は、本書に添付された演習用スクリプト param.pl の一部として含まれています。 SELECT ステートメントに加えて、スクリプトにはパラメーター・マーカーを使用した UPDATE ステ ートメントを実行する例が含まれています。このコード例をテストする場合には、ユーザーIDとパス ワードを適宜編集して実行します。 perl param.pl 以下の図 9.4 は、param.pl スクリプトの実行結果です。 332 DB2 アプリケーション開発入門 図 9.4 – param.pl の実行 9.3.5 ストアード・プロシージャー・コール DB2 ストアード・プロシージャーを perl アプリケーションから呼び出すには、以下の手順に従いま す。 1 DB2->connect メソッドを呼び出して、データベースに接続します。 2 データベース・ハンドルの prepare メソッドを呼び出してストアード・プロシージャー・ステートメ ントの呼び出し準備をします。準備の処理が成功するとステートメント・ハンドルを戻します。 例えば、リスト 9.9 に示されたような SQL プロシージャー sp_get_employees を呼びたいと 仮定しましょう。。 CREATE PROCEDURE sp_get_employees (IN dept_no CHAR(3), OUT dept_name VARCHAR(36)) DYNAMIC RESULT SETS 1 BEGIN DECLARE emp_cursor CURSOR WITH RETURN TO CLIENT FOR SELECT firstnme, lastname FROM employee WHERE workdept=dept_no; OPEN emp_cursor; SELECT deptname INTO dept_name FROM department WHERE deptno=dept_no; END @ リスト 9.9 – sp_get_employees.db2 sp_get_employees は、入力パラメーター dept_no と出力パラメーター dept_name とい う2つのパラメーターを持っています。また、カーソル emp_cursor で定義されているクライア ントに結果セットを戻すことも行います。 次のように CALL ステートメントを準備することができます: $sthandle = $dbhandle->prepare( "CALL sp_get_employees(?,?)" ); 第 9 章 - Perl によるアプリケーション開発 333 2つのパラメーターが CALL ステートメントで”?”というパラメーター・マーカーとして表示されて います。準備に成功すると、ステートメント・ハンドルが変数 $sthandle に戻されます。 3 ステートメントの bind_param メソッドまたは bind_param_inout メソッドをコールしてローカ ル の Perl 変 数 や 値 に パ ラ メ ー タ ー を 関 連 付 け ま す 。 bind_parm_inout メ ソ ッ ド は IN/INOUT/OUT パラメーターに使われますが、bind_param メソッドは IN パラメーターの関 連づけにのみ使われます。 bind_param メソッドの構文については前述の節を参照してください。bind_param_inout メソッドの構文は以下のとおりです。 $rv = $sth->bind_param_inout($p_num, \$bind_value, $max_len, \%attr) 表 9.4 は bind_param_inout のパラメーターの詳細を示しています。 Name Description $p_num CALL ステートメント内のパラメーターの 1 で始まるインデックスの位置を指 定します。 $bind_value $max_len \%attr $p_num で指定されたパラメーターにバインドされている Perl 変数もしく は値。OUT/INOUT パラメーターなら変数が使用され、それ以外の場合 は、変数または値を指定できます。 $bind_value に割り当てるメモリーの最小値を指定できます。 オプション:パラメーターの型、精度、スケールを指定するため使用すること ができます。 表 9.4 – ステートメント・ハンドルの bind_param_inout method パラメーター 例えば、ステップ 2 で準備された CALL ステートメントを考えると、以下リスト 9.10 のように、 “A00”という値を最初の入力パラメーターにバインドするために bind_param を呼び、 $deptname を2つ目の出力パラメーターバインドするために bind_param_inout を呼ぶ事 ができます。 $sthandle->bind_param(1,"A00"); $sthandle->bind_param_inout (2, \$deptname, 36, {'TYPE'=>SQL_VARCHAR}); リスト 9.10 – パラメーターのバインド 4 この CALL ステートメントを実行するために、 ステートメント・ハンドルの execute メソッドを呼 び出します。SQL プロシージャーが 1 つ以上の結果セットを返すようになっていれば、 execute の呼び出しが成功すると、ステートメント・ハンドルと結果セットが関連付けられます。 その後、前節 9.3.2 で触れたように結果セットから行を抽出をするために fetchrow_array() といったフェッチ関数を使う事ができます。もし複数の結果セットがあった場合、次の結果セッ トに変更するため、例えば $sth-> [db2_more_results]のようにステートメント・ハンドルの db2_more_results メソッドを使う事ができます。 前の手順で準備した CALL ステートメントを実行するために、以下を実行します: 334 DB2 アプリケーション開発入門 $sthandle-> execute(); CALL ステートメントの実行が成功した後、結果セットはステートメントに関連付けられます。そ の結果セットから行のフェッチを始めることができます。 上記のコードの例は本書に添付されている演習ファイルのスクリプト sp.pl の一部です。もしコード 例をテストしたい場合、本書添付の DB2 のスクリプト sp_get_employees.db2 に定義されてい る SQL プロシージャー sp_et_LastName を最初に作成するために以下のコマンドを実行する必 要があります。 db2 connect to sample db2 -td@ -f sp_get_employees.db2 db2 terminate スクリプト sp.pl ユーザーID とパスワードを適切に修正して以下のように実行します。 perl sp.pl スクリプト sp.pl の実行結果を図 9.5 に示します。 図 9.5 – sp.pl の実行 9.4 演習 演習 1 こ の 演 習 で は 、 最 初 に 有 効 な DB2 V9.7 が 導 入 さ れ て い る と い う 前 提 で 、 SUSE Linux Enterprise Server 10 SP1 の環境に Perl DB2 をセットアップします。セットアップを実行するには、 root ユーザーでなければならないことに注意してください。セットアップ手順は他のオペレーティン グ・システムと似ています。 1 Perl 5.8 以上を導入します。 第 9 章 - Perl によるアプリケーション開発 335 Perl 5.8.8 は SUSE Linux Enterprise Server 10 SP1 で標準に導入されますので、別途 Perl の言語環境を導入する必要はありません。Perl 言語のバージョンを調べるには以下のシ ェルを実行します。 perl - v もし Perl のバージョンが 5.8 より低い場合は、9.2 節 で Perl 言語を導入するインストールす る方法を参照してください。 2 Perl DBI モジュールを導入します。l z 最新の Perl DBI ソース・ファイルを http://search.cpan.org/~timb/DBI/ からダウンロ ードします。本書作成時点では DBI ソースは DBI-1.611.tar.gz が最新となっています。 z ルートユーザーで Linux サーバーにログインし、DBI-1.611.tar.gz が置かれたディレク トリーで以下のコマンドを実行します。 tar xvfz DBI-1.611.tar.gz cd DBI-1.611 perl Makefile.PL make make test make install 3 DBD::DB2 モジュールを導入します。 z 最新の DBD::DB2 ソース・ファイルをhttp://www.ibm.com/software/data/db2/perl/ か らダウンロードします。本書作成時点では DBD::DB2 ソースの最新は DBD-DB21.78.tar.gz となっています。 z root ユーザーで以下のコマンドを実行します。 export DB2_HOME=/home/db2inst1/sqllib perl Makefile.PL make make test make install 注: /home/db2inst1 は DB2 イ ン ス タ ン ス 所 有 者 の ホ ー ム ・ デ ィ レ ク ト リ ー で 、 /home/db2inst1/sqllib はインスタンスのバイナリ・ファイルが置かれている場所です。ここ では、インスタンス所有者は db2inst1 という前提となっています。 演習 2 この演習では、サンプルデータベースからデータにアクセスするための小さなスクリプトを書いて練 習します。 1 インスタンス所有者(例えば、”db2inst1”、ないしは Windows の”db2admin”)としてサーバー にログオンします。 336 DB2 アプリケーション開発入門 2 SAMPLE データベースが以前に作成されていない場合は、DB2 コマンド・ウィンドウないしは Linux のシェルから次のコマンドを実行します。 db2sampl 3 “SOFTWARE SUPPORT”部門で作業しているすべての従業員を抽出する為の Perl スクリ プトを記述します。同時に、この部門で ‘1996-01-01' 以前に雇われた各従業員の給与を 5% の給与を増やします。 4 スクリプトの作成ができない場合には、本書添付にて提供されたスクリプト perl_ex1.pl が解決 策となります。適切なユーザーID とパスワードに修正して以下のようにテスト実行してください。 perl perl_ex1.pl 9.5 まとめ この章では、DB2 と作業するための Perl の環境をどのようにセットアップするか、SQL ステートメン トの実行方法や標準 Perl DBI インターフェースによって Perl アプリケーションからのどのようにスト アード・プロシージャーの呼ぶかといった事について学びました。 9.6 確認問題 1 Perl アプリケーションでDB2データベースにアクセスするために使う API は何ですか? 2 Perl DBI と データベース DBD ドライバーの関係は何ですか? 3 Perl スクリプトで DB2 データベースにアクセスする標準的なデータベース・インターフェース は次のうちどれですか? A CLI B 組み込み Perl C. Perl DBI D JDBC E 上記以外 4 パラメータマーカーを持つ SQL を実行するための手順は、次のうちどれですか? A prepare, bind_param, execute B prepare, bind_variable, do C prepare, bind_param, do D prepare, 実行, fetchrow_array E 上記以外 第 9 章 - Perl によるアプリケーション開発 5 337 最初に準備をすることなく、直接 SQL ステートメントを実行する事ができるのは以下のどれで すか? A exec_immediate B execute C do D execute_imm E 上記以外 10 第 10 章 - Python によるアプリケーション開発 Python はプラットフォーム非依存のインタープリター・プログラミング言語であり、無償で使用でき、 Windows、Linux、Unix、Max OS X といった多くのオペレーティング・システムで使用できます。 Python は Python Software Foundation (http://www.python.org/)で管理されているオープン・ ソース言語環境です。Python が持つオブジェクト指向の特性や柔軟なデータ型定義といった側 面により、多数提供される標準提供ライブラリーと相まって、迅速なアプリケーション開発向けの人 気のある言語になっており、データベース・アプリケーションにも利用されています。 本章では、以下の内容についてご説明します。 DB2 を利用する Pytyon 環境のセットアップ Python アプリケーションから DB2 データベースへの接続 DB2 データにアクセスする Python アプリケーションの開発 Note: Phyton プログラミング言語を体験するのが初めてである場合は、この本のシリーズ中の無償の eBook である「Getting Started with Python」をチェックしてみてください。 この章では既に DB2 で提供される SAMPLE データベースを作成していることを前提としていま す。まだ作成していない場合は、db2smpl コマンドを使って作成してください。 10.1 Python – DB2 アプリケーション:概要 Python アプリケーションは DB2 データ・サーバーに対し Python DB2 API およびドライバーやア ダプターを介してアクセスします。利用したいデータベース API に応じて、選択可能な様々なドラ イバーやアダプターが存在します。これらの API やドライバー・アダプターの概要が図 10.1 に図 示されています。 340 DB2 アプリケーション開発入門 図 10.1 – DB2 にアクセスするための Python DB2 API とドライバー・アダプターの概要 図 10.1 に示されているとおり、DB2 データ・サーバーにアクセスするための Python アプリケーシ ョンでは、4 種類の異なるデータベース API とドライバー・アダプターが選択可能です。それら API とドライバー・アダプターは次項以降で説明します。 10.1.1 IBM が定義している API と ibm_db ドライバー これは IBM によって定義された Python 専用のデータベース API セットとなります。Ibm_db ドライ バーはその API を実装したものとなります。この API を利用すると、SQL ステートメントを発行した り、ストアード・プロシージャーを呼び出したり、pureXML を使ったりできるだけではなく、DB2 のメ タデータ情報へのアクセスも Python アプリケーションからできるようになります。 ibm_db ドライバーは、DB2 固有の CLI/ODBC インターフェースに対する Python の C 言語拡張 モジュールとして実装されています。そのため、最高のパフォーマンス性能と最大限の先進的な機 能を提供することができます。後ほどこのドライバーについてはさらに詳細を説明します。 Note: Ibm_db API の仕様についてはhttp://code.google.com/p/ibm-db/wiki/APIsをご覧ください。 10.1.2 Python Database API と ibm_db_dbi ドライバー Python Database API は Python アプリケーション向けに定義されたオープンスタンダードなデ ータベース API です。Ibm_db_dbi ドライバーは ibm_db ドライバー上に構築された Python で 記述されたラッパーであり、Standard Python Database API Specification に準拠したデータベ ース API を提供していますが、ibm_db ドライバーと同様に、これらの標準 API を通じて SQL ステ ートメントの発行やストアード・プロシージャーの呼び出しが可能になっています。この API は標準 仕様に準拠しているので、ibm_db API がサポートしているような先進的な機能のいくつかは利用 することができません。しかしながら、Python Database API Specification をサポートしたドライバ ーを使ってアプリケーションを記述すれば、ibm_db_dbi ドライバーに簡単に移行することが可能 です。 この本が執筆されている現時点では、Python Database Specivication V2.0 が ibm_db_dbi ドラ イバーでサポートされています。 第 10 章 - Python によるアプリケーション開発 341 Note: Python Database API はデータベース管理システムへの Python インターフェースの実装に対す る 標 準 的 な 仕 様 で す 。 Python Database API Specification の 詳 細 に つ い て は 、 http://www.python.org/dev/peps/pep-0249/で確認できます。 10.1.3 SQLAlchemy と ibm_db_sa アダプター SQLAlchemy はオープン・ソースの Python SQL ツールキットであり、アプリケーション開発者が SQL の柔軟性を最大限享受することができる Object Relational Mapper です。SQLAlchemy は ”SQL expression language” と呼ばれ、通常の SQL ステートメントを使う代わりに、機能に 基づいたクエリー構文を利用することで Python の機能や記法を利用してデータベースへアクセス することが可能になります。Ibm_db_sa アダプターは ibm_db_dbi ドライバーを利用する Python で記述された DB2 アダプターであり、SQLAlchemy API のサポートを実現しています。 この本を執筆している時点では、SQLAlchemy 0.4 Specification API が ibm_db_sa アダプター でサポートされています。 Note: SQLAlchemy の情報は、API リファレンス込みでhttp://www.sqlalchemy.org/で確認することがで きます。 10.1.4 Django フレームワークと ibm_db_django アダプター Django は迅速なアプリケーション開発によく利用されているオープン・ソースの Python の Web イ ンターフェースです。SQLAlchemy と同様に、Django フレームワーク API によって通常の SQL ステートメントを使うのではなく Python の機能と記法を利用してデータベースへアクセスすることが 可能になります。ibm_db_django アダプターは ibm_db_dbi ドライバーを利用する Python で記 述された DB2 アダプターであり、Django フレームワーク API のサポートを実現しています。 この本を執筆している時点では、Django 1.2 specification API がサポートされています。 Note: Django フレームワークの情報は、API リファレンス込みでhttp://www.djangoproject.com/.で確認 することができます。 10.2 環境のセットアップ DB2 と動作を行うように Python の環境をセットアップするには、以下の手順に従います: 1. Python 2.5 以降をインストールします。 以下のどれかの手順で Python をインストールできます。 バイナリー配布物の ActivePython を利用してインストールします。 ActivePython は ActiveState Software によって提供されている無償の Python のバイナ リ ー 配 布 物 で あ り 、 多 く の オ ペ レ ー テ ィ ン グ ・ シ ス テ ム で 動 作 し ま す 。 Web サ イ ト ( http://www.activestate.com/activepython/downloads/ ) か ら ダ ウ ン ロ ー ド で き 、 342 DB2 アプリケーション開発入門 Windows では Windows インストーラーから、Linux や Unix では install.sh から Python をインストールできます。 Windows では、もう一つの方法として Web サイト( http://www.python.org/download/ ) から無償の Python の Windows インストーラーをダウンロードすることもでき、Windows イ ンストーラーを実行することでインストールできます。 も ち ろ ん 、 全 て の オ ペ レ ー テ ィ ン グ ・ シ ス テ ム に お い て 、 Web サ イ ト ( http://www.python.org/download/ )から無償でダウンロードできるソースからビルドする という方法も可能です。 例として、ソースから Linux 上で Python 2.5.4 をビルドしてインストールするためには、ソ ースとして Python-2.5.4.tgz をダウンロードして、"tar -zxvf Python-2.5.4.tgz"として解凍 します。その後、Python-2.5.4 というディレクトリーに移動して"./configure"、"make"、 "make install"のコマンドを実行し、Python のコンパイルとインストールを行います。 以下を実行することで Python のバージョンを確認することが出来ます python –V 2. setuptools のインストール setuptools は、Python のパッケージのダウンロード、ビルド、インストール、アップグレード、 アンインストールを行うための無償のプログラムです。http://pypi.python.org/pypi/setuptools/ からダウンロードでき、Web サイト上の手順にしたがってインストールできます。このツールは、 いくつかの Python DB2 ドライバーを導入するために後ほど必要になります。 3. IBM DB2 データ・サーバー・クライアントのインストール 上記ソフトウェアのインストール後、Python DB2 アダプターとドライバーをインストールすることがで きます。 10.2.1 Python アダプターとドライバー 全ての Python-DB2 アダプターとドライバーはhttp://code.google.com/p/ibm-db/downloads/list から無償でダウンロードできます。また、ibm_db および ibm_db_dbi ドライバーとソースは http://pypi.python.org/pypi/ibm_dbからもダウンロードできます。 前セクションで説明したように、利用したいデータベース API にしたがってどのドライバーおよびア ダプターをインストールするかを決めることが出来ます。例として、IBM が定義した API からでも Python データベース API からでも加工なしの SQL ステートメントを発行したいのであれば、 ibm_db および ibm_db_dbi ドライバーをインストールして下さい。SQLAlchemy もしくは Django フレームワークを使いたければ、ibm_db_sa もしくは ibm_db_django アダプターだけではなく、こ れらのアダプターのベースとなっている ibm_db および ibm_db_dbi アダプターもインストールしな ければなりません。 10.2.1.1 ibm_db および ibm_db_dbi ドライバーのインストール ibm_db および ibm_db_dbi ドライバーは ibm_db パッケージという一つのインストール用パッケ ージに同梱されています。これらは両方ともインストールされている必要があります。この文書を記 第 10 章 - Python によるアプリケーション開発 343 述している現時点では、これらの最新のリリースは 1.0.2 であり、Linxu および Windows でサポー トされています。 1. ibm_db パッケージのインストール インターネットへのアクセスが可能であれば、図 10.2 で示すように、Windows 上で次のコ マンドを実行します: easy_install ibm_db 図 10.2 easy_insall を使ったインターネット経由での ibm_db および ibm_db_dbi の インストール 図 10.2 で示しているように、easy_install コマンドはインターネットからパッケージをダウ ンロードし、setuptools がインストールされている site-packages ディレクトリーの下に 2 つのドライバーをインストールします。easy_install は事前にインストールされている setuptools パッケージによって提供されるプログラムです。 もしインターネットへの接続がない場合、http://code.google.com/p/ibmdb/downloads/list,からプラットフォームに合わせた適切な Python の”egg”ファイルをダウ ンロードし、次のコマンドを実行します: easy_install <egg_file_name> <egg_file_name>の部分には egg ファイルへのパスを含めてください。 たとえば、図 10.3 に示すように、ibm_db-1.0.2-py2.5-win32.egg というダウンロードされ た”egg”ファイルを使用してドライバーをインストールすることができます。 344 DB2 アプリケーション開発入門 図 10.3 – easy_install を使用した egg ファイルから ibm_db および ibm_db_dbi のイ ンストール また、ソース・コードからドライバーをビルドしてインストールすることもできます。 http://pypi.python.org/pypi/ibm_db/. からコードをダウンロードします。手順はそのドライ バーのソース・コードとともに配布されている README ファイル中で表されています。ソ ース・コードに含まれている C プログラムをコンパイルするために、プラットフォーム上に C コンパイラーが必要となります。 17. PYTHONPATH という名前の環境変数を作成し、ibm_db の egg がインストールされて いるパスを指定します。たとえば: - Windows の場合 PYTHONPATH=<setuptools_install_path>\site-packages\<ibm_dbxx.egg> - Linux (BASH シェル)の場合 export PYTHONPATH=<setuptools_install_path>/sitepackages/<ibm_db-xx.egg> 18. コマンド・プロンプトから、python と打ち込んで Python の対話式のインタープリターを開 始し、接続をテストするためにリスト 10.1 のようなコードを入力することによって、セットア ップしたものをテストします。 (1) import ibm_db (2) ibm_db_conn = ibm_db.connect('SAMPLE', 'db2admin', 'password') (3) import ibm_db_dbi (4) conn = ibm_db_dbi.Connection(ibm_db_conn) (5) conn.tables('SYSCAT', '%') リスト 10.1 – インストール確認のための DB2 データベース接続テスト リスト 10.1 では以下のようになっています 第 10 章 - Python によるアプリケーション開発 345 (1) ibm_db モジュールをインポートします。 (2) SAMPLE データベースに ibm_db.connect 関数を使って接続を作成し、ユーザーID に”db2admin”、パスワードに”password”を指定します。これらの変数の内容は適切に 置き換えて下さい。Ibm_db.connect については後ほどの章でさらに議論します。 (3) ibm_db_dbi モジュールをインポートします。 (4) ibm_db_dbi.Connection という関数を呼び出します。 (5) SYSCAT スキーマに属するすべての表をリストします。 10.2.1.2 ibm_db_sa アダプターのインストール 執筆時点では、SQLAlchemy 0.4 をサポートする最新版のリリース 0.1.6 の ibm_db_sa アダプタ ーが Linux と Windows で使用可能となっています。 以下が ibm_db_sa アダプターのインストールおよびセットアップの手順です。 2. ibm_db_sa パッケージのインストール インターネットへの接続ができる場合、以下のコマンドを実行してください。 easy_install ibm_db_sa このコマンドによって、インターネットからパッケージがダウンロードされ、site-packages ディレクトリー以下にドライバーがインストールされます。このドライバーは ibm_db と ibm_db_dbi ドライバーおよび SQLAlchemy にも依存しているので、easy_install によ ってこれらが以前インストールされていなかった場合はこれらをダウンロードしインストール します。 例として、Windows では図 10.4 のようにインターネットからアダプターをインストールでき ます。 346 DB2 アプリケーション開発入門 図 10.4 – easy_install を使ったインターネットからの ibm_db_sa のインストール 図 10.4 に示すとおり、easy_install コマンドは、ibm_db_sa パッケージや ibm_db、 ibm_db_dbi そして SQLAlchemy といったインターネットから事前に導入しておかなけ ればならない全パッケージが事前にインストールされていない場合や、setuptools がイン ストールされている site-packages ディレクトリー以下にインストールされていない場合に、 これらのファイルをダウンロードします。 イ ン タ ー ネ ッ ト に ア ク セ ス で き る 環 境 が な い 場 合 、 Python egg フ ァ イ ル を http://code.google.com/p/ibm-db/downloads/listからダウンロードし、次のコマンドを実 行します: easy_install <egg_file_name> <egg_file_name>には egg ファイルへのパスが含まれます。 例として、次のように指定します: easy_install ibm_db_sa-0.1.6-py2.5.egg 第 10 章 - Python によるアプリケーション開発 347 インターネットへのアクセスができない場合、ibm_db_sa パッケージを導入する前に、依 存関係のある ibm-db と SQLAchemy パッケージを最初にインストールしておくようにして 下さい。 3. コマンド・プロンプトから、python とタイプして Python インタープリターを起動し、リスト 10.2 のようなコードを入力して DB2 への接続をテストすることで、セットアップした環境を テストします。 (1) import sqlalchemy from sqlalchemy import * (2) db2 = sqlalchemy.create_engine('ibm_db_sa://db2admin:password @localhost:50000/SAMPLE') (3) metadata = MetaData() (4) users = Table('users', metadata, Column('user_id', Integer, primary_key = True), Column('user_name', String(16), nullable = False), Column('email_address', String(60), key='email'), Column('password', String(20), nullable = False) ) (5) metadata.bind = db2 (6) metadata.create_all() 図 10.2 – DB2 データベースへ接続してインストールをテストする リスト 10.2 では以下のようになっています (1) sqlalchemy パッケージをインポートします。 (2) “db2”というデータベース・エンジン・オブジェクトを作成します。そこの”SAMPLE”は接 続 し よ う と し て い る SAMPLE デ ー タ ベ ー ス で あ り 、 ”db2admin” は ユ ー ザ ー ID、”password”はパスワード、”localhost:50000”は 50000 番ポートを listen している ローカルのインスタンスを表しています。 (3) metadata という MetaData オブジェクトを作成します。 (4) USERS という名前の表を定義します。 (5) db2 エンジンへそのメタデータ・オブジェクトをバインドします。 (6) CREATE ステートメントを全テーブルへ発行します。 10.2.1.3 ibm_db_django アダプターをインストールする 執筆時点では、Django 1.2 をサポートしている ibm_db_django アダプターの 0.2.1 という最新リリ ースが Linux と Windows で使用可能です。 Ibm_db_django アダプターのインストールとセットアップの手順は次のようになっています: 4. Django フレームワークをインストールします。 348 DB2 アプリケーション開発入門 ibm_db_django アダプターは Django フレームワークパッケージに依存しているので、 ibm_db_django アダプターをインストールする前に Django フレームワークをインストー ルする必要があります。 Django フレームワークは次の Django ウェブサイトにある手順に従ってインストールしま す: http://docs.djangoproject.com/en/dev/topics/install/#installing-an-official-release もし Django 1.0.2 を使用しているのであれば、非標準の SQL 生成といった問題を取り除 くために Django にパッチを適用する必要があります。1.0.2 以上のバージョンではパッチ は必要ありません。パッチの詳細は次を参照します: http://code.djangoproject.com/ticket/9862 creation.py ファイルを次の場所にあるパッチの zip ファイルから解凍します: http://code.djangoproject.com/changeset/9703?format=zip&new=9703 この creation.py を site-packages/django/db/backends/にある Django インストール・デ ィレクトリーへコピーします。 19. ibm_db と ibm_db_dbi ドライバー 0.7.2.5 以上を、もしインストールしていなければイン ストールします。詳細は前セクションの ”ibm_db と ibm_db_dbi ドライバーのインストー ル” を参照してください。 20. ibm_db_django パッケージをインストールします。 ibm_db_django の ソ ー ス ・ コ ー ド で あ る ibm_db_django-x.x.x.tar.gz を http://code.google.com/p/ibm-db/downloads/listからダウンロードします。x.x.x はドライ バーのバージョンを表します。 ibm_db_django-x.x.x.tar.gz を解凍します。 インストールするには次のコマンドを実行します: cd ibm_db_django python setup.py install 21. DB2 への接続をテストし、ibm_db_django アダプターのインストールを検証します。 次を実行して新規 Django プロジェクトを作成します。 django-admin.py startproject myproj 新規作成されたディレクトリーへ移動し、リスト 10.3 に示されたように settings.py ファイル を編集します。 (1) DATABASE_ENGINE = 'ibm_db_django' (2) DATABASE_NAME = 'SAMPLE' (3) DATABASE_USER = 'db2admin' (4) DATABASE_PASSWORD = 'password' リスト 10.3 – setteings.py 第 10 章 - Python によるアプリケーション開発 349 上記は以下のようになっています。 (1) “ibm_db_django” は DB2 データベース・サーバーへアクセスしたいということを意味 しています。これは django アダプターのバージョン 0.1.2 からの新しいフォーマットで す。以前の django アダプターでは代わりに DATABASE_ENGINE = 'db2'を使用します (2) “SAMPLE” は SAMPLE データベースを表します。 (3) “db2admin” はユーザーID です。環境に合わせて書き換えて下さい。 (4) “password” はパスワードです。環境に合わせて書き換えて下さい。 次のようにテストを実行します: python manage.py test Note: 上述した全 4 つの Python DB2 ドライバーのオープン・ソースプロジェクトのホームサイトは http://code.google.com/p/ibm-db/ からアクセス可能です。 10.3 Python DB2 アプリケーションの開発 単純化するために、このセクションでは ibm_db ドライバーのみにフォーカスします。このドライバ ーは DB2 データ・サーバーへアクセスするのに最高のパフォーマンスと先進機能を提供していま す。他の全ドライバーとアダプターに関しては、API 仕様書を参照してください。 10.3.1 DB2 データベースへの接続 最初に、ibm_db ドライバー・モジュールをインポートするために Python スクリプトに以下の行を 含めます: import ibm_db その後、次の構文を使って ibm_db.connect 関数を呼び出して DB2 データベースへ接続しま す。 IBM_DBConnection ibm_db.connect (string dsn, string user, string password[, array options]) 表 10.1 に ibm_db.connect のパラメーターを説明しています。 名前 内容 dsn データベース接続文字列。次のフォーマットで表します: "DATABASE=database; HOSTNAME=hostname; PORT=port; PROTOCOL=TCPIP; UID=username; PWD=password;" user データベースの接続に使用するユーザー名。ユーザー名を dsn 文字列の中 で指定する場合は空文字列を指定します。 password データベースの接続に使用するパスワード。パスワードを dsn 文字列の中で 350 DB2 アプリケーション開発入門 指定する場合は空文字列を指定します。 options 任意指定。接続に関する挙動を指定するオプションのリスト。 表 10.1 – ibm_db.connect 関数のパラメーター たとえば、SAMPLE がクライアントでローカル・カタログされているデータベース別名である場合、 リスト 10.4 で示すようにして接続を作成できます。 import ibm_db conn = ibm_db.connect("SAMPLE","db2admin","password") リスト 10.4 – ローカル・カタログされた SAMPLE データベースへの接続 SAMPLE データベースが 50000 番ポートをリッスンしているインスタンスがあるマシン host2 にあ るリモート・データベースであり、クライアントでカタログされていない場合は、リスト 10.5 で示すよう に TCP/IP 経由で直接接続することができます。 import ibm_db conn = ibm_db.connect("DATABASE=SAMPLE; HOSTNAME=host2; PORT=50000; PROTOCOL=TCPIP; UID=db2admin; PWD=password;", "", "") リスト 10.5 – TCP/IP 経由でのリモートの SAMPLE データベースへの直接接続 接続が成功したら、ibm_db.connect 関数は ibm_db.IBM_DBConnection オブジェクトを返し ます。その接続オブジェクトは、後のデータベース操作で使用されます。例えばデータの抽出、挿 入、更新、そして削除といった SQL ステートメントで使用します。 Note: Ibm_db ドライバーは永続性の接続の生成もサポートします。その接続はクローズされた後もコネク ション・プールに活性化したまま残り、認証情報の固有のセットがある場合には後続する接続要求 を許可し既存の接続を再利用します。詳細情報は、http://code.google.com/p/ibm-db/wiki/APIs にある ibm_db.pconnect 関数の API 仕様書を確認して下さい。 10.3.2 データの読み出し アプリケーション開発時に SQL ステートメントが確定していない場合、変数とパラメーター・マーカ ーを含んだ SQL を実行することも可能です。詳細は 10.3.4 節 を参照して下さい。 SQL ステートメントがあらかじめ決まっている場合は、以下の手順でデータを選択し取得すること が可能です: 1. ibm_db.connect 関数でデータベースに接続します。接続が成功すると、データベース接続 オブジェクトが返されます。 2. ibm_db.exec_immediate 関数を呼び出して SQL の SELECT ステートメントを直接実行しま す。実行に成功する場合、結果セットに関連づけられたステートメント・オブジェクトが返されます。 jbm_db.exec_immediate 関数の構文は以下に示すとおりです: IBM_DBStatement ibm_db.exec_immediate( IBM_DBConnection connection, string statement [, array options] ) 第 10 章 - Python によるアプリケーション開発 351 表 10.2 では ibm_db.exec_immediate での各パラメーターを説明しています。 名前 内容 connection ibm_db.connect()から返される有効なデータベース接続オブジェクト。 Statement 文字列書式の SQL ステートメント。ステートメントはパラメーター・マーカーを含 むことはできません。すなわち、ステートメントは記述される時点でわかっている べきということです。 任意指定:ステートメントのオプションを含んだリスト。スクロール可能なカーソ ルを、それをサポートするデータベース・サーバーに対してリクエストを行うとき に使います。デフォルトでは、順方向のカーソルが返されます。 表 10.2 – ibm_db.exec_immediate 関数のパラメーター options 例えば、ibm_db.exec_immediate 関数を呼び出し、以下に示すように文字列の引数として与 えられた SELECT ステートメントを実行することができます。 stmt = ibm_db.exec_immediate(conn, 'SELECT firstnme, lastname FROM employee fetch first 2 rows only') ここでは、その関数はステップ 1 で返された接続オブジェクト conn を最初の引数として使い、 実行が成功する場合、クエリーの結果セットが関連づけられたステートメント・オブジェクトである stmt が返されています。 3. 結果セットから行を読み出すのには ibm_db.fetch_tuple()を呼び出します。これは結果セットに ある次もしくはリクエストされた行を表しているタプルを返します。それぞれの列の値はタプルの 0 で始まる列の位置によって索引化されています。 Ibm_db.fetch_tuple 関数の構文は以下に示すとおりです: array ibm_db.fetch_tuple(IBM_DBStatement stmt, [, int row_number]) 表 10.3 で ibm_db.fetch_tuple のパラメーターを説明します。 名前 Stmt 内容 結果セットを含んだ有効なステートメント・オブジェクト 任意指定:結果セットから取り出したい特定の行を表す 1 で始まる行番号。そ の結果セットが順方向のカーソルを利用している場合は、このパラメーターを 指定すると警告が返されます。 表 10.3 – ibm_db.fecht_tuple 関数のパラメーター row_number 結果セットにこれ以上行がない場合、もしくは row_number で要求されている行が結果セットに ない場合、この関数は False を返します。 例えば、リスト 10.6 に示すように結果セットから全行を取り出して表示することができます。 (1) mytuple = ibm_db.fetch_tuple(stmt) 352 DB2 アプリケーション開発入門 (2) while mytuple != False: (3) print "First Name: %s, Last Name: %s" % (mytuple[0], mytuple[1]) (4) mytuple = ibm_db.fetch_tuple(stmt) リスト 10.6 – 結果セットからの行の取り出し リスト 10.6 は以下のように説明できます: (1) ibm_db.fetch_tuple 関数は、結果セットからそれぞれの行をタプルとして返し、mytuple 変数に入れます。 (2) その関数が結果セットに行がなくなって False を返すまで繰り返します。 (3) mytyple[0], mytuple[1]のように 0 で始まる列の位置を使うことで、返された行からそれぞ れの列の値を表示します。 (4) 次の行を取り出し mytuple 変数へ入れます。 Note: ibm_db.fetch_tuple に加え、ibm_db ドライバーは ibm_db.fetch_assoc,、 ibm_db.fetch_both、そして ibm_db.fetch_row といった柔軟な結果セットの抽出をサポートす る 3 つのデータ抽出関数も提供しています。更なる情報はhttp://code.google.com/p/ibmdb/wiki/APIsをみてください。 上記のコードの断片を全てテストしたい場合、この本に付属の練習用ファイルに含まれている Python のスクリプトである select.py を編集し、ユーザーID とパスワードを必要に応じて置き換え てください。その後、次のように実行します: python select.py 上記スクリプトを実行した結果は図 10.5 に示すようになります。 図 10.5 select.py スクリプトの実行 Note: こ の 章 で 使 わ れ て い る 全 ス ク リ プ ト は こ の 本 に 付 属 の zip フ ァ イ ル で あ る Exercise_Files_DB2_Application_Development.zip の中のディレクトリーsamples/chapter10 に含まれています。 スクリプトの実行には、最初に db2sampl ユーティリティーを利用して SAMPLE データベースを 第 10 章 - Python によるアプリケーション開発 353 作成する必要があります。またスクリプトのユーザー名とパスワードは必要に応じて置き換えてくだ さい。 10.3.3 データの挿入、更新、削除 SELECT ステートメントと同様に、INSERT、UPDATE、DELETE といった SQL ステートメントで、 事前に内容が確定しているものは ibm_db.exec_immediate 関数を呼び出すことで直接実行で きます。変数入力やパラメーター・マーカーを含んだ SQL ステートメントについては、セクション 10.3.4 を参照してください。 SQL ステートメントの実行が成功した後、ibm_db.num_rows 関数を使って SQL ステートメント が作用した行数を返すことができます。 リスト 10.7 の例を見てみましょう。 (1) stmt = ibm_db.exec_immediate(conn, "CREATE TABLE PRODUCT(product_id char(6), name char(30))") (2) stmt = ibm_db.exec_immediate(conn, "Insert into PRODUCT values ('000001','computer'), ('000002','TV')") (3) print "Returns for insert: ", ibm_db.num_rows(stmt) (4) stmt = ibm_db.exec_immediate (conn, "update PRODUCT set name = 'notebook' where product_id='000001'") (5) print "Returns for update: ", ibm_db.num_rows(stmt) (6) stmt = ibm_db.exec_immediate (conn, "delete from PRODUCT where product_id='000003'") (7) print "Returns for delete: ", ibm_db.num_rows(stmt) (8) stmt = ibm_db.exec_immediate (conn, "drop table PRODUCT") リスト 10.7 – ins_upd_del.py スクリプト リスト 10.7 の要素は以下のように説明できます: (1) ibm_db.exec_immediate 関数を呼び出し、PRODUCT 表を作成します。 (2) ibm_db.exec_immediate 関数を呼び出し、PRODUCT 表に行を挿入します。 (3) 挿入された行数を表示します。 (4) 表の数行を更新します。 (5) 更新された行数を表示します。 (6) 表の数行を削除します。 (7) 削除された行数を表示します。 (8) 表をドロップします。 上記のコードは本に付属の練習ファイルに含まれている ins_upd_del.py スクリプトの一部です。ス クリプトのユーザーID とパスワードを適切に変更してコードをテストでき、次のように実行します。 python ins_upd_del.py スクリプトの実行結果は図 10.6 のようになります。 354 DB2 アプリケーション開発入門 図 10.6 – ins_upd_del.py スクリプトの実行 10.3.4 パラメーター・マーカーを含んだ SQL の実行 前出の 2 つのセクションでは、アプリケーション記述時にわかっている SQL ステートメントを実行す るための ibm_db.exec_immediate 関数の使い方を学びました。ここでは、実行時までわからな い変数入力を含んだ SQL ステートメントの実行方法を練習しましょう。 クエスチョン・マーク(?)文字は SQL ステートメント文字列の中で各変数入力に対応するパラメー ター・マーカーとして使用されます。このようなステートメントの準備と実行の手順は以下のように説 明できます: 1. ibm_db.connect によりデータベースに接続します。接続が成功するとデータベース接続オブ ジェクトが返されます。 2. ibm_db.prepare 関数を使用してパラメーター・マーカーを使った SQL 文字列を準備します。 準備の試行が成功すると IBM_DBStatement ステートメント・オブジェクトが返されます。 Ibm_db.prepare 関数の構文は次の通りです: IBM_DBStatement ibm_db.prepare( IBM_DBConnection connection, string statement [, array options] ) 表 10.4 では ibm_db.prepare 関数のパラメーターが記述されています。 名前 内容 connection ibm_db.connect()から返された有効なデータベース接続オブジェクト Statement 文字列形式の SQL ステートメント。オプションで入出力パラメーター・マーカー を含みます。これらの変数は SQL が実行されるまでわかりません。 任意指定:ステートメントのオプションを含むリストです。このパラメーターを使っ てスクロール可能なカーソルをそれをサポートするデータベース・サーバーに 要求することができます。デフォルトでは前方専用のカーソルが返されます。 表 10.4 – ibm_db.prepare 関数のパラメーター options この関数は SQL が正常に準備できるとステートメント・オブジェクトを返し、失敗した場合は例外 (Exception)を発生します。 例えば、以下のようにパラメーター・マーカーを含む SELECT ステートメントを準備できます: 第 10 章 - Python によるアプリケーション開発 355 stmt = ibm_db.prepare(conn, "SELECT empno, lastname, job, salary FROM employee WHERE workdept = ?") 上 に 示 し た よ う に 、 conn 接 続 オ ブ ジ ェ ク ト は 関 数 の 第 一 引 数 と し て 渡 さ れ 、 第 二 引 数 に は ”workdept = ?” で表される述部のパラメーター・マーカーを含んだ SELECT 文字列となってい ます。パラメーター・マーカー”?”は SQL 実行時にに指定される部門コード(work dept)の変数を 表しています。ibm_db.prepare が正常に SQL ステートメントを準備できると、その関数はステー トメント・オブジェクトを返し、stmt 変数に関連づけられます。 3. 各パラメーター・マーカーに対して ibm_db.bind_param 関数を呼び出し、入力変数を SQL のパラメーター・マーカーにバインドします。 ibm_db.bind_param 関数の構文は以下のようになっています: Py_True/Py_None ibm_db.bind_param(IBM_DBStatement stmt, int parameter-number, string variable [, int parameter-type [, int data-type [, int precision [, int scale [, int size[]]]]]] ) 表 10.5 では ibm_db.bind_param 関数のパラメーターが記述されています。 名前 内容 stmt ibm_db.prepare()から返された準備済みのステートメント Parameternumber 準備済みのステートメントの中のパラメーターの 1 から始まる位置を指定しま す。 variable パラメーター番号で指定されたパラメーターと結びつけられた Python 変数 Parametertype 任意指定:パラメーター・マーカーの種類。入力パラメーター (SQL_PARAM_INPUT)や出力パラメーター(SQL_PARAM_OUTPUT)、も しくは入力を受け付け出力を返すパラメーター (SQL_PARAM_INPUT_OUTPUT)の場合があります。また、メモリーのオー バーヘッドを回避するために、Python 変数を大きなオブジェクト(BLOB、 CLOB、DBCLOB)を含んだファイルの名前に結びつけるために PARAM_FILE を指定できます。デフォルトでは SQL_PARAM_INPUT となり ます。 data-type 任意指定:Python 変数が SQL_BINARY、DB2_CHAR、DB2_DOUBLE、 DB2_LONG のうちの一つとしてバインドされる SQL データ型を指定する定 数。 precision 任意指定:変数がデータベースにバインドされる述部を指定します。 scale 任意指定:変数がデータベースにバインドされるスケールを指定します。 size 任意指定:INOUT/OUT パラメーターから抽出されるサイズを指定します。 表 10.5 – ibm_db.bind_param 関数のパラメーター バインドが成功する場合関数は True を返し、失敗する場合は例外(Exception)をあげます。 356 DB2 アプリケーション開発入門 例えば、以下のように ibm_db.bind_param を呼び出し、”A00” という変数を手順 2 で準備され た SELECT ステートメントの中のパラメーター・マーカーにバインドします。 ibm_db.bind_param(stmt, 1, "A00") 実行が成功すると、”A00” の値は SQL の述部 ”workdept = ?” のパラメーター・マーカー(?)とバ インドされます。 4. ibm_db.execute() 関数を呼び出して SQL ステートメントを実行します。 ibm_db.execute 関数の構文は以下のようになります: Py_True/Py_False ibm_db.execute(IBM_DBStatement stmt [, tuple parameters]) 表 10.6 では ibm_db.execute()のパラメーターを記述しています。 名前 stmt 内容 ibm_db.prepare()から返される準備されたステートメント 任意指定:準備されたステートメントに含まれるパラメーター・マーカーにマッチ する入力パラメーターの組。bind_param 関数をパラメーターとバインドするた めに呼び出した場合はオプションとなります。 表 10.6 – ibm_db.execute 関数のパラメーター parameters SQL の実行が成功した場合関数は True を返し、失敗したら例外(Exception)があがります。実 行する SQL が SELECT ステートメント、もしくは1つ以上の結果セットを返すストアード・プロシー ジャー(ストアード・プロシージャーの呼び出しは後のセクションでさらに議論します)を CALL する 場合、結果セットはステートメント・オブジェクトに関連づけられます。その後、前のセクション 10.3.4 で議論したように結果セットから行を取り出すために ibm_db.fetch_tuple のような編集抽 出関数を使えます。 例えば、以下のようにして前の手順で準備された SELECT ステートメントを実行できます: ibm_db.execute(stmt) SQL ステートメントの実行に成功した後、結果セットはステートメントに関連づけられます。結果セッ トから行の抽出を始めることができます。 上記のコードはこの本に付属の練習用ファイルに含まれる param.py スクリプトの一部です。 SELECT ステートメントに加え、そのスクリプトはパラメーター・マーカーを含んだ UPDATE ステー トメントの実行の例も含んでいます。コードをテストしたい場合、ユーザーID とパスワードを適切に 変更して以下のように実行します: python param.py param.py スクリプトの実行結果は図 10.7 のようになります。 第 10 章 - Python によるアプリケーション開発 357 図 10.7 – param.py スクリプトの実行 10.3.5 ストアード・プロシージャーの呼び出し Python アプリケーションからストアード・プロシージャーを呼び出すには以下の手順に従います: 1. ibm_db.connect 関数でデータベースに接続することでデータベース接続オブジェクトを作成 します。 2. ibm_db.callproc 関数を呼び出すことでストアード・プロシージャーを呼び出すと、ステートメン ト・オブジェクトを最初の要素、パラメーターのコピーの修正されたものを残りの要素とするタプル が返されます。そのステートメント・オブジェクトがもしある場合はストアード・プロシージャーから 返された結果セットを含んでいますが、OUT と INOUT パラメーターが可能性のある新しい値に 置き換えられ、入力パラメーターが変更されることはありません。複数の結果セットがある場合は、 例えば stmt1 = ibm_db.next_result(stmt)のように最初の引数として元のステートメントのリソースを 与えることにより ibm_db.next_result メソッドを呼び出し、次の結果セットに移動することがで きます。 ibm_db.callproc の構文は次の通りです: tuple ibm_db.callproc ( IBM_DBConnection connection, string procname, [,tuple parameters] ) 表 10.7 では ibm_db.callproc のパラメーターを記述しています。 名前 内容 connection ibm_db.connect()から返された有効なデータベース接続オブジェクト。 procname 呼び出すストアード・プロシージャーの名前。 parameters 任意指定:パラメーターの組はそのプロシージャーが期待するそれぞれのパラ メーターに対して一つずつのエントリーを含まなくてはいけません。ストアード・ プロシージャーがパラメーターを含まない場合はオプションとなります。 358 DB2 アプリケーション開発入門 表 10.7 – 関数 ibm_db.callproc のパラメーター Note: 執筆時、ibm_db.callproc 関数はストアード・プロシージャーの呼び出しを新たにサポートするた めの新しい関数です。この関数はどのようなストアード・プロシージャーを呼び出すにも使用すべき です。prepare / bind_param / executeといった関数でも CALL ステートメントを通じて IN パラ メーターとともにストアード・プロシージャーを呼び出せていました。 例えば、リスト 10.8 に定義されているような SQL プロシージャーである sp_get_employees を取 り上げましょう。 CREATE PROCEDURE sp_get_employees (IN dept_no CHAR(3), OUT dept_name VARCHAR(36)) DYNAMIC RESULT SETS 1 BEGIN DECLARE emp_cursor CURSOR WITH RETURN TO CLIENT FOR SELECT firstnme, lastname FROM employee WHERE workdept=dept_no; OPEN emp_cursor; SELECT deptname INTO dept_name FROM department WHERE deptno=dept_no; END @ リスト 10.8 – sp_get_employees.db2 上記 SQL プロシージャーは 2 つのパラメーターを有しています。dept_no は入力パラメーターで あり、dept_name は出力パラメーターです。そしてカーソル emp_cursor に定義されているよう な一つの結果セットをクライアントへ返すことになります。 その後、リスト 10.9 に表しているようにストアード・プロシージャーを呼び出すことができます。 deptno=’A00’ deptname=’’ (1) stmt, deptno,deptname=ibm_db.callproc( conn, "sp_get_employees", (deptno, deptname)) (2) mytuple = ibm_db.fetch_tuple(stmt) while mytuple != False: print "First Name is : %s, Last Name is : %s" % (mytuple[0], mytuple[1]) mytuple = ibm_db.fetch_tuple(stmt) 表 10.9 – 関数 ibm_db.callproc の呼び出し そこでは以下のようになっています: 第 10 章 - Python によるアプリケーション開発 359 (1) deptno はストアード・プロシージャーの dept_no パラメーターに対する入力値を含んだ Python 変数であり、deptname は dept_name パラメーターの出力値を含んだ変数です。実 行が成功した後、関数は stmt 変数でステートメント・オブジェクトを返し、deptname 変数は変 更されて出力パラメーターの値を持つことになりますが、入力変数 deptno は変更ありません。 その SQL プロシージャーはまた一つの結果セットを返しますが、ステートメント・オブジェクトは SQL プロシージャーから返される結果セット含むことになります。 (2) 前のセッションで行ったように、ステートメント・オブジェクトに関連づけられた結果セットから行 を取り出します。 上記コードはこの本に付属しているスクリプト sp.py の一部です。コードをテストしたい場合、この本 に付属している db2 スクリプト sp_get_employees.db2 に定義されている SQL プロシージャー sp_get_lastname を最初に作成する以下のコマンドを実行する必要があります: db2 connect to sample db2 -td@ -f sp_get_employees.db2 db2 terminate また、スクリプト sp.py の中のユーザーID とパスワードを適切に変更し以下のように実行します: python sp.py スクリプト sp.py の実行結果は図 10.8 のようになります: 図 10.8 – スクリプト sp.py の実行 10.4 課題 この課題では、SAMPLE データベースのデータにアクセスする小さな Python スクリプトを記述す る練習をします。 1. サーバーにインスタンス・オーナーとしてログオンします(例:Linux では db2inst1、Windows では db2admin) 360 DB2 アプリケーション開発入門 2. まだ実行していない場合は、次のコマンドで SAMPLE データベースを作成します: db2sampl 3. “SOFTWARE SUPPORT”という部署で働く全従業員を表示する Python スクリプトを記述し ます。同時に、この部署に’1996-01-01’以前に雇用されたそれぞれの従業員に対して給料を 5%昇級します。 4. このスクリプトを作成するのに問題が生じる場合、解決法はこの本に付属のスクリプト python_exl.py で提供されています。そのスクリプトのユーザーID とパスワードを適切に変更 し、以下のようにテストします: python python_ex1.py 10.5 まとめ この章では、Python アプリケーションから DB2 データ・サーバーにアクセスできる数種類の Python DB2 ドライバーとアダプターおよび API を議論しました。また、ibm_db ドライバーおよび API を呼び出す Python アプリケーションからどのように SQL ステートメントの実行を行いストアー ド・プロシージャーの呼び出しを行うのかといった方法を提供しています。 10.6 練習問題 1. Python アプリケーションが DB2 データベースにアクセスするためのドライバーもしくはアダプ ターは何ですか? 2. ibm_db と ibm_db_dbi ドライバーの主な違いは何ですか? 3. 通常の SQL ステートメントの代わりに、クエリーを組み立てるのに Python 関数と構文を使うこ とをサポートしているのはどのドライバーもしくはアダプターでしょうか? 4. 次の API のうち pureXML の使用やメタデータへのアクセスといった DB2 の先進の機能をも っともサポートしているのはどれでしょうか? A. ibm_db B. ibm_db_dbi C. ibm_db_sa D. ibm_db_django E. None of the above 5. 次の手順のうち、パラメーター・マーカーを含んだ SQL を実行する手順はどれでしょう? A. prepare, bind_param, execute B. prepare, bind_variable, exec_immediate C. prepare, bind_param, exec_immediate D. prepare, execute, fetchrow 第 10 章 - Python によるアプリケーション開発 361 E. None of the above 6. 次の関数のうち、最初に準備することなしに直接 SQL を実行することができるのはどれでしょ うか? A. execute B. exec_immediate C. execute_immediate D. execute_imm E. None of the above 7. 次の関数のうち、ストアード・プロシージャーを呼び出すのに使えるのはどれでしょうか? A. exec_proc B. execute_call C. callproc D. procall E. None of the above A 付録 A – 確認問題の解答 第1章 1. ストアード・プロシージャーを使うことでネットワークのトラフィックを軽減できるのでパフォー マンス上の優位性があります。 2. ユーザーはユーザー定義関数(UDF)を開発することで SQL 言語を拡張できます。 3. CLI は ODBC のスーパーセットです。 4. 静的 SQL はプリコンパイル時に SQL ステートメントが確定しています。動的 SQL は実 行時に情報が与えられます。 5. Type 2 ドライバーを使うには、DB2 クライアントがインストールされている必要がありま す。 6. D. 上記全て。 7. E. いずれも該当しない。 8. C. ODBC と JDBC は常に動的 SQL を使用している。 9. C. DB2 .NET Data provider 10. D. ibm_db_python 第2章 1. リレーショナル・データベース技術が世に出てから 30 年近くになります。これは、堅牢で 信頼性が高く、かつ、安全に高いパフォーマンスで情報を取得する技術です。XML は他 のデータと同様にデータなので、XQuery を処理できるようにデータベース・エンジンに幾 つかの変更/修正を加えて、XML をデータデースに保存することは理に適っています。 2. 2つの種類とは、昔からある XML 対応データベースと、DB2 がサポートしているネイティ ブ XML データベースのことです。 3. pureXML の特徴: (1) XML は(XML 文書のフォーマットである)階層フォーマットでデータ ベースに保存されます。 (2) DB2 エンジンに XQuery/XPath を使用して XML をネイティ ブに処理することが可能な部分があります。 364 DB2 アプリケーション開発入門 4. 一般的にコードが小さくなります。それによって、実行・保守すべき命令が少なくなります。 コードが小さくなるのは、XML 文書を辿るために木を構築して構文解析することが不要に なるためです。構文解析は、XML 文章を最初にデータベースに挿入する時に実行されま す。 5. 2 つの方法があります。(1)単純に SQL INSERT ステートメントを使用します。そこで、 XML 文書をシングルクォートで囲んで渡します。(2)ファイルから挿入したい時には、DB2 IMPORT ユーティリティーを使用します。 6. E. 上記全て。 XML 文章全体であれば、SQL 自身で XML データを取得することが可能 です。その一部を欲しい場合には、SQL/XML または XQuery を使用しなければなりませ ん。 7. E. XMLNAVIGATE 8. C. XMLQUERY は、XQuery 関数ではなく SQL/XML 関数です。 9. C. TRANSFORM 式を使用します。 10. E. 上記何れでもない。XML インデックスは、値に対しても作成可能です。 XML スキーマ レポジトリは、DB2 データベースの内部に保存されます。そして、XML 文章は BEFORE トリガーで妥当性検査されます。 第3章 1. ストアード・プロシージャーの利点としては、以下の点が挙げられます。 z ネットワーク・トラフィックを削減します; これにより、パフォーマンスが向上します。 z ロジックをデータベースに集中させます。そのため、多くのクライアント・アプリケ ーションが使用できるような一般的なストアード・プロシージャーをかくことができ ます。 z ユーザーが明示的なアクセス権限を持たないオブジェクトに対する操作を実行 できます。ストアード・プロシージャーを通して、制御されたアクセス権限を使用 することができます。 2. いいえ。外部スカラー・ユーザー関数は UPDATE 処理を実行することはできません。そ のような処理には、表関数を使用してください。 3. 外部スカラー・ユーザー関数は、以下の二つの方法で呼び出すことができます: z values ステートメントを使用する z SELECT ステートメントを使用する 4. いいえ。BEFORE トリガーは UPDATE は実行できません。BEFORE トリガーは、 INSERT の前にデータの妥当性を確認するために使用できます。トリガー・アクションの中 で UPDATE 処理を実行するには、AFTER トリガーを使用してください。 付録 A – 確認問題の解答 365 5. SPECIFIC キーワードは、ストアード・プロシージャーに一意の名前を付与します。ストア ード・プロシージャーはオーバーロードすることができるため、一意の名前はプロシージャ ーの管理に役立ちます。 6. B. Present。 これは有効なトリガーではありません。 7. D. IBM Data Studio はトリガーの作成には使用できません。 8. E. C と D はどちらも有効です。'AS' キーワードは任意です。 9. B. XML は、SOAP か REST かに関わらず、Web サービスの基礎のテクノロジーとして 使用されています。 10. B. DB2 9.7 以降、ユーザー定義関数とトリガーは SQL PL を完全にサポートしています。 DB2 9.7 より前のバージョンでは、SQL PL 言語のサブセットである、インライン SQL PL のみをサポートしていました。 第4章 1. JDBC は Java を使って動的 SQL でデータベースにアクセスするための標準規格です。 SQLJ は組み込まれた静的 SQL ステートメントのための標準規格です。 2. JDBC タイプ 2 とタイプ 4 です。 3. db2jcc.jar は JDBC 3.0 の仕様に則したドライバー・ファイルで、db2jcc4.jar は JDBC 4.0 の仕様の一部とそれ以前の仕様をサポートします。 4. SQLJ のイテレーターは JDBC の ResultSet と等価です。プログラム内のループを通し て、処理された複数の行を返します。 5. デフォルト・コンテキストは、SQLJ プログラムで特定の接続コンテキストが指定されないと きに利用されるコンテキストです。例えば、’ctx1’ をデフォルト・コンテキストとして指定し、 ステートメントに接続コンテキストを指定しなかった場合、デフォルト・コンテキストの ‘ctx1’ が利用されます。 6. E. 上記のいずれでもない。db2jcc.jar と db2jcc4.jar は JDBC タイプ 2 と JDBC タイプ 4 の両方を含んでいます。 7. D. 上記の全て。pureQuery は ORM と共に利用することもできます。pureQuery は ORM を尊重しています。 8. D. JDBC と SQLJ と pureQuery は連携させることができる。 9. D. ResultSetStatement は正しいオブジェクトではありません。 10. 実行可能コンテキストは存在しません。実行コンテキストです 第5章 366 DB2 アプリケーション開発入門 1. CLI/ODBC は組み込み動的 SQL の代替方法ですが、組み込み SQL とは違って、これ はホスト変数またはプリコンパイラーを必要としません。アプリケーションは、さまざまなデ ータベースに対して個別にコンパイルすることなしに実行することができます。 2. カーソルは、アプリケーション・プログラム内で行のセットの中の特定の行を指すために使 用される制御構造です。 3. クエスチョン・マーク (?) によって示されるパラメーター・マーカーは、ステートメント実行中 に値が取得される SQL ステートメント内のプレースホルダーです。 4. ハンドルは、プログラムの各部分の間で変数への参照を受け渡しするために使われるポイ ンター変数です。 5. SQL_SUCCESS SQL_SUCCESS_WITH_INFO SQL_INVALID_HANDLE SQL_ERROR 6. C. Windows での組み込み SQL の C++アプリケーションの拡張子は.sqx です。 7. B. db2bfd –s はバインド・ファイルから SQL ステートメントをダンプすることができるコマン ドです。 8. C. db2 list system odbc data sources 9. A. SQLAllocHandle () API はすべてのハンドルを割り振るために使われます 10. A. 環境ハンドルの割り振り -> 接続ハンドルの割り振り -> ステートメント・ハンドルの割り振 り-> ステートメント・ハンドルの解放 -> 接続ハンドルの解放 -> 環境ハンドルの解放 第6章 1. FieldCount プロパティーは現在行の列の数を返します。一方、HasRows プロパティーは DataReader が 1 行以上のデータを持っているかどうかを true または false で示します。 2. 接続設定の Step 1 で、DB2 データベースを ODBC データ・ソースとして追加でカタログす る必要があります。 3. ADO.NET のデータ・アクセスは 2 つのコンポーネント DataSet とデータ・プロバイダーに依 存しています。 DataSet DataSet は非接続型の、メモリー上に展開されたデータ表現形式です。これはデータベ ースのある一部のローカル・コピーとして扱えます。DataSet はアプリケーションのメモリ ー上に常駐し、その中のデータはデータベースとは独立して操作や更新可能です。 DataSet 上での操作が完了すると、変更をデータベースに反映できます。DB2 などす べての有効なデータ・ソースから DataSet にデータをロードできます。 データ・プロバイダー 付録 A – 確認問題の解答 367 データ・プロバイダーは、データベース接続を提供し、これを維持します。各データ・プロ バイダーは効率的でパフォーマンスを意識したデータの提供を行う一連のコンポーネン トであり、複数のコンポーネント クラスによって構成されています。 4. 32 ビット版の IBM Data Server Provider for .NET を使って、64 ビット Windows インスタン ス上で 32 ビット .NET アプリケーションを実行できます。64 ビットのコンピューターで 32 ビッ ト版の IBM Data Server Provider for .NET を使うには、IBM Data Server Driver Package の 32 ビット版をインストールします。 5. IBM Database Add-ins for Visual Studio を 使 用 す る に は http://www.ibm.com/db2/express/download.html からダウンロードします。DB2 製品をイン ス ト ー ル 後 、 db2exc_vsai_xxx_WIN_x86.exe 実 行 フ ァ イ ル を ダ ブ ル ク リ ッ ク し て IBM Database Add-Ins for Visual Studio をインストールできます。ここで xxx は DB2 サーバー と一致するバージョン番号です。 6. A 7. C 8. D 9. B 10. C 第7章 1. Ruby on Rails は、Web アプリケーションを開発するためのフレームワークです。RoR は、 MVC アーキテクチャーに準拠し、開発者が迅速に高品質のアプリケーションを提供でき るようにするため、「構成よりも規則優先」 ("Convention Over Configuration - CoC")、 「同じことを繰り返さない」 ("Do not Repeat Yourself - DRY") という指針を採用していま す。 2. ibm_gem は DB2 に接続するための Ruby ドライバーとアダプターを含む gem です。次 のコマンドで導入できます。 3. gem install ibm_db 4. Rails から DB2 への接続は、ibm_db gem で提供されます。この gem は Ruby が DB2 と通信するためのドライバー(C 言語)と、アクティブ・レコードを通じて DB2 を操作するた めの Ruby 言語で記述されたアダプターを含んでいます。アクティブ・レコードはリレーシ ョナル表をオブジェクト指向クラスにマッピングする ORM レイヤーです。 5. database.yml ファイルは、ホスト名、ポート番号、ユーザーID、パスワード、アダプター名 などの DB2 と接続するために必要な情報を保管しています。 6. 可能です。DB2 は XQuery も実行可能ですので、XML データに簡単にアクセスできま す。 368 DB2 アプリケーション開発入門 7. C.「新しいバージョンを導入する前に、古いバージョンを削除する必要がある」は、誤りで す。 8. A. gem は標準化されたパッケージフォーマットですが、Ruby はプログラミング言語です。 9. C. IBM_DB アダプターは IBM データ・サーバーと接続するために、IBM Driver for ODBC and CLI を使用します。 10. A. Account は必須ではありません。 11. B 第8章 1. その名が示すとおり、非永続接続は各 db2_close の後に接続を切断してリソースを開放 するか、あるいは接続リソースは NULL にセットされるか、スクリプトが終了します。 永続接続の場合、接続リソースは db2_close の後あるいはスクリプトが終了しても接続リ ソースは開放されません。新しい接続が要求されるたびに、PHP は同じ認証情報で接続 を再利用しようとします。 2. 接続プーリングは先に確立された古い接続を再利用することで新しい接続を減らすため、 データベース・アプリケーションのパフォーマンス向上に役立ちます。接続プーリングは短 時間に接続が確立される際に有効です。 3. 以下の行を httpd.conf ファイルに追加することで Apache HTTP サーバー2.x での PHP サポートを有効にします。Phpdir は PHP が導入されたディレクトリーを示します。 4. LoadModule php5_module 'phpdir/php5apache2.dll' 5. AddType application/x-httpd-php .php 6. PHPIniDir 'phpdir' 7. 設定パスを確認するには、php –I コマンドを実行し、php.ini キーワードを探します。 8. 既に Unified ODBC で記述されたアプリケーションについて、ソース・コード内全体の関 数名を odbc_ を db2_ に変更するだけで容易に ibm_db2 拡張 API へ移植することが できます。 9. D 10. B 11. D 12. C 13. A 第9章 1. Perl Databse interface (DBI) 2. 標準の Perl DBI は、Perl アプリケーションに対するデータベース・インターフェースを提 供しています。このインターフェースは、バックグラウンドで DBD ドライバーをロードし、こ の DBD ドライバーがデータベースとのやり取りを行います。 3. C 4. A 5. C 第 10 章 1. ibm_db, ibm_db_dbi, ibm_db_sa, ibm_db_django 2. ibm_db は IBM 自身によって定義された独自のデータベースの API のセットを実装して おり、さらに ibm_db_dbi は ibm_db ドライバー上のラッパーであり、標準の Python Databese API の仕様をサポートしています。 3. ibm_db_sa と ibm_db_django 4. A 5. A 6. B 7. C B 付録 B – トラブルシューティング この付録では、DB2 を利用する際に直面する可能性がある問題への対応方法をご説明します。図 B.1 は問題発 生時に取るべきアクションの概要です。 db2 ? <code> Review Administration Notification Log Review db2diag.log Problem! Review system with Operating System commands Search for APARs, or known problems Collect Traces, dumps, trap files, core files and contact IBM DB2 Tech Support 図 B.1 - トラブルシューティング概要 注: 372 DB2 アプリケーション開発入門 トラブルシューティングに関しての詳細は、以下のビデオをご覧ください。 http://www.channeldb2.com/video/video/show?id=807741:Video:4462 B.1 エラー・コードに関しての詳細の確認 返されたエラー・コードに関しての 詳細を得るためには、コマンド・エディターの入力欄に、疑問符に続いてエラ ー・コードを入力し、実行ボタンをクリックしてください。図 B.2 で示しています。 図 B.2 - DB2 のエラー・コードに関しての詳細の確認 疑問符 (?) で DB2 のヘルプを実行することができます。以下は、例えば SQL エラー・コードとして “-104” を受け 取った際のヘルプの実行方法の例です。 db2 ? SQL0104N db2 ? SQL104N db2 ? SQL-0104 db2 ? SQL-104 db2 ? SQL-104N B.2 SQLCODE と SQLSTATE SQLCODE は SQL ステートメントが実行されたあとに返されるコードです。値の意味を要約すると以下となります。 SQLCODE = 0; コマンドは成功しました。 SQLCODE > 0; コマンドは成功しましたが、警告が返されました。 SQLCODE < 0; コマンドは失敗し、エラーが返されました。 SQLSTATE は、ISO/ANSI SQL92 標準に則した 5 文字の文字列です。最初の 2 文字は SQLSTATE クラス・ コードとして知られています。 00 のクラス・コードは、コマンドの成功を示します。 付録 B – トラブルシューティング 373 01 のクラス・コードは、警告を示します。 02 のクラス・コードは、データが無いことを示します。 他の全てのクラス・コードは、エラーを示します。 B.3 DB2 管理通知ログ DB2 管理通知ログは、エラー発生時の問題判別のための情報を提供します。Linux と UNIX 環境では、管理通 知ログは <インスタンス名>.nfy (例えば “db2inst.nfy”) という名前のテキスト・ファイルです。Windows 環境では、 全ての管理通知メッセージは Windows イベント ログに出力されます。 管理者は DBM 構成パラメーターの notifylevel によって記録される情報のレベルを変更することができます。 0 – 管理通知メッセージはキャプチャーされません。 (非推奨) 1 – 致命的エラー、またはリカバリー不能エラー。 2 – 即時アクションが必要です。 3 -- 重要な情報ですが、即時アクションの必要はありません。(デフォルト) 4 – 通知メッセージ。 B.4 db2diag.log db2diag.log は、DB2 管理通知ログ以上に詳細な情報を提供します。通常は IBM DB2 テクニカル・サポートや 経験のあるデータベース管理者が利用します。db2diag.log には以下のような情報が含まれます。 エラーを報告している DB2 内のコードの位置 サーバーとクライアントの db2diag.log で、あるアプリケーションに関連するエントリーを付き合わせて確認 するための、アプリケーション ID の情報 エラーの理由を説明する (“DIA”から始まる) 診断メッセージ SQLCA データ構造のようなユーザーが利用可能なサポート情報や、ダンプ・ファイルやトラップ・ファイル などの出力先の情報 Windows 環境 (Vista 以前) では、db2diag.log はデフォルトでは以下のディレクトリーにあります。 C:\Documents and Settings\All Users\Application Data\IBM\DB2\DB2COPY1\<instance name> Windows 環境の Vista 以降では、db2diag.log はデフォルトでは以下のディレクトリーにあります。 C:\ProgramData\IBM\DB2\DB2COPY1\<instance name> Linux と UNIX 環境では、db2diag.log はデフォルトでは以下のディレクトリーにあります。 /home/<instance_owner>/sqllib/db2dump 診断テキストの情報量は、DBM 構成パラメーターの diaglevel で決められます。設定値は 0 から 4 で、0 は最も 情報量が少なく、4 は最も多くなります。デフォルトは 3 です。 374 DB2 アプリケーション開発入門 B.5 CLI トレース CLI や Java (DB2 JDBC Type 2 Driver for Linux, UNIX and Windows を利用する場合) 、PHP、Ruby on Rails などのアプリケーションを利用する場合、アプリケーションの問題判別のために CLI トレースを利用できます。 アプリケーションが稼働しているサーバーに存在する db2cli.ini を変更することで、CLI トレースを利用できます。 db2cli.ini ファイルに記述する代表的なエントリーは以下のリスト B.1 のようなものです。 [common] trace=0 tracerefreshinterval=300 tracepathname=/path/to/writeable/directory traceflush=1 リスト B.1 - CLI トレースを有効にするための db2cli.ini ファイルのエントリー より詳細なレベルのトレース (db2trc) も利用可能ですが、このトレースは通常 DB2 テクニカル・サポートのみが利 用します。 B.6 DB2 の障害と修正 直面した問題が、DB2 の障害によって発生している場合もあります。IBM は通常、障害 (APAR) に対する修正コ ードを含んだフィックスパックをリリースしています。フィックスパックのドキュメントにはフィックスパックに含まれる修 正のリストが載っています。新しいアプリケーションを開発する時には、最新の修正が適用されている状態とするた め、最新のフィックスパックをご利用いただくことを推奨いたします。現在ご利用いただいているフィックスパックの レベルを確認するためには、コントロール・センターからの場合、ヘルプメニューから情報を選択してください。コマ ンド・ウィンドウからの場合、db2level と入力してください。DB2 Express-C には、フィックスパックや IBM DB2 テ クニカル・サポートは提供されないため、ご注意ください。DB2 Express-C では、修正はフィックスパックとして適 用するのではなく、インストール・イメージに含まれています。 参考文献 [1] ZIKOPOULOS, P. IBM® DB2® Universal Database™ and the Microsoft® Excel Application Developer… for Beginners, dbazine.com article, April 2005 http://www.dbazine.com/db2/db2disarticles/zikopoulos15 [2] ZIKOPOULOS, P. DB2 9 and Microsoft Access 2007 Part 1: Getting the Data..., Database Journal article, May 2008 http://www.databasejournal.com/features/db2/article.php/3741221 [3] BHOGAL, K. Use Microsoft Access to interact with your DB2 data, developerWorks article, May 2006. http://www.ibm.com/developerworks/db2/library/techarticle/dm-0605bhogal/ [4] CHUN, J., CIRONE P. DB2 packages: Concepts, examples, and common problems, developerWorks article, June 2006 http://www.ibm.com/developerworks/data/library/techarticle/dm-0606chun/index.html [5] CHEN Whei-Jen et all. DB2 Express-C: The Developer Handbook for XML, PHP, C/C++, Java, and .NET August 2006 - SG24-7301-00 http://www.redbooks.ibm.com/abstracts/sg247301.html?Open 関連情報 Web サイト 1. DB2 Express-C web site: www.ibm.com/db2/express DB2 Express-C サーバーや DB2 クライアント、DB2 ドライバー、マニュアルのダウンロード、チーム・ブロ グへのアクセス、メーリング・リストへの登録などの際は、こちらの Web サイトをご利用ください。 2. DB2 Express-C forum: www.ibm.com/developerworks/forums/dw_forum.jsp?forum=805&cat=19 マニュアルから答えが見つからない時には、フォーラムへ技術的な質問の投稿してください。 3. DB2 Information Center http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp インフォメーション・センターは、オンラインでアクセスできるマニュアルです。ここにある情報が最新の情報 です。 4. developerWorks http://www-128.ibm.com/developerworks/db2 この Web サイトは最新の記事やチュートリアルなどを無償で提供しており、開発者やデータベース管理者 にとっては非常に有益な情報です。 5. alphaWorks http://www.alphaworks.ibm.com/ この Web サイトは、IBM の発展途上の技術へのアクセスを提供します。IBM の研究から生まれた最新の 技術について触れることができます。 376 DB2 アプリケーション開発入門 6. planetDB2 www.planetDB2.com DB2 に関してのブログを書いている多くの方々からのブログの情報が集約されています。 7. DB2 Technical Support DB2 Express-C の 12 ヶ月間のサブスクリプションを購入している場合、この Web サイトからフィックスパッ クをダウンロードできます。 http://www.ibm.com/software/data/db2/support/db2_9/ 8. ChannelDB2 ChannelDB2 は DB2 コミュニティーのためのソーシャル・ネットワークです。Linux、UNIX、Windows、 z/OS、i5/OS の DB2 に関連したビデオやデモ、ポッドキャスト、ブログ、ディスカッション、関連情報などの コンテンツを扱っています。 http://www.ChannelDB2.com/ 本 1. Free Redbook: DB2 Express-C: The Developer Handbook for XML, PHP, C/C++, Java, and .NET Whei-Jen Chen, John Chun, Naomi Ngan, Rakesh Ranjan, Manoj K. Sardana, August 2006 - SG24-7301-00 http://www.redbooks.ibm.com/abstracts/sg247301.html?Open 2. Understanding DB2 – Learning Visually with Examples V9.5 Raul F. Chong, et all. January 2008 ISBN-10: 0131580183 3. DB2 9: pureXML overview and fast start by Cynthia M. Saracco, Don Chamberlin, Rav Ahuja June 2006 SG24-7298 http://www.redbooks.ibm.com/abstracts/sg247298.html?Open 4. DB2® SQL PL: Essential Guide for DB2® UDB on Linux™, UNIX®, Windows™, i5/OS™, and z/OS®, 2nd Edition Zamil Janmohamed, Clara Liu, Drew Bradstock, Raul Chong, Michael Gao, Fraser McArthur, Paul Yip ISBN: 0-13-100772-6 5. Free Redbook: DB2 pureXML Guide Whei-Jen Chen, Art Sammartino, Dobromir Goutev, Felicity Hendricks, Ippei Komi, Ming-Pang Wei, Rav Ahuja, Matthias Nicola. August 2007 http://www.redbooks.ibm.com/abstracts/sg247315.html?Open 6. Information on Demand - Introduction to DB2 9 New Features Paul Zikopoulos, George Baklarz, Chris Eaton, Leon Katsnelson ISBN-10: 0071487832 Resources ISBN-13: 978-0071487832 コンタクト先のメールアドレス General DB2 Express-C mailbox: [email protected] General DB2 on Campus program mailbox: [email protected] 377 DB2 アプリケーション開発入門は、最も易しい入門書です。 本書は以下のような目的のためお読みください: DB2 Express-C を使って DB2® アプリケーション開発を体験する SQL や XQuery を書いて、pureXML® の技術を理解する DB2 のストアード・プロシージャーや関数、データ Web サービスの開発方法を 学ぶ JavaTM や C/C++、.NET、PHP、Ruby on Rails、Perl、Python などのアプリケ ーションで DB2 を利用する方法を学ぶ DB2 のデータベースに関連した問題のトラブルシューティング ハンズ・オン形式の演習問題による練習 IBM が提供する DB2 Express-C は、リレーショナル・データと XML データを容易に管理 できる DB2 データ・サーバーの無償のエディションです。無償とは、DB2 Express-C を自 由にダウンロードし、自由にアプリケーションを開発し、自由に製品にデプロイし、自由にソ リューションに組み込み提供することができることを意味しています。また、DB2 はデータ ベースのサイズやデータベースの数、ユーザーの数に意図的な制限を加えていません。 ® ® DB2 Express-C は Windows や Linux 、Solaris、Mac OS X で稼働し、C/C++ や Java、.NET、Ruby on Rails、PHP、Perl、Python を含む、様々なプログラミング言語 やフレームワークのためのアプリケーション・ドライバーを提供しています。より優れたスケ ーラビリティーや更なる高機能をお求めの場合、DB2 Express-C を利用して構築されたア プリケーションを、DB2 Workgroup Edition や DB2 Enterprise Edition などの他のエディ ションへ、シームレスに移行することが可能です。 この無償のエディションの DB2 は、開発者やコンサルタント、ISV、データベース管理者、 学生、その他の開発やテスト、デプロイ、データベース・アプリケーションの配給などを目的 としたどなたでもご利用いただけます。現在成長を続けている DB2 Express-C のユーザ ー・コミュニティーに参加し、DB2 Express-C をテスト運用にご利用ください。次世代のア プリケーションの作り方や革新的なソリューションの提供方法を、ぜひご体験ください。 よ り 詳 細 な 情 報 や DB2 Express-C の ダ ウ ン ロ ー ド の た め に は 、 http://www.ibm.com/db2/express をご参照ください。 ソーシャル・ネットワークに参加する際や関連するビデオをご覧いただく際は、 http://www.channelDB2.com をご参照ください。 この本は、コミュニティーのための eBook である DB2 on Campus のシリー ズの一部です。詳細は http://www.db2university.com をご参照ください。 Price: 24.99USD
© Copyright 2024 Paperzz