「Delphi6Personalでデータベース」についてとりとめもなく考える
(2004/6/26 くわわっ記)■まえがき
Delphi6Personalを使ってお手軽にリレーショナルデータベースを扱うことはできないでしょうか。本来、Delphiはデータベースアプリケーションがとてもつくりやすい開発環境です。ただその実は、TDataBaseなどのデータベース用のとても便利なインターフェース(つまりコントロール)が、添付されてくるということであり、ところがそれは有償版のProfessional以上にしか添付されていません。じゃあ、何とかTDataBaseなしでデータベースアプリをつくるにはどうしたらいいか考えてみよう、というのがそもそも発端です。
あと一応、「SQLって何?」とかって言う質問はなしにしてください。私も偉そうにいえるレベルではありませんが、内容的にはその程度の予備知識が前提だってことです。
ここで何かの業務目的がありつつこのページたどりついた皆様、以下の点にご注意ください。
まず、業務目的でDelphi6Personalを使うのはライセンス違反です。いけません。
それとあくまで私的な好奇心がもともとの動機になっていますので、業務向けにはあまりに非効率的な内容となっています。業務に生かすことは費用対効果で考えても時間の無駄ですので、おやめになったほうがいいです。あくまで「どうやればいいんだろう?」「どうなってるんだろう?」という純粋な好奇心に共鳴いただける方を対象といたします。
もう一点、あらかじめ宣言しておきますが、筆者はこのページを書く1年前までリレーショナルデータベースの何たるかも知らなかった全くの素人です。内容に多くを期待することはおやめください。筆者は体系的な学習や経験も積んでおりません。このページ内容の大半は限りなくインチキです。コード実例など自分でお試しになる場合には、かならず自己責任でやってください。どんな危険なマチガイが含まれているか、わかりません。
■目次
ADO編
DAO編
ODBC編
■設定条件
以下の考察では、下記の条件下であることを前提とします。
・OSはWindowsXP(たぶん95以降であれば同じと思います(*1)が、保証はできません。何せテストしてませんので。)
・Delphi6Personalがインストールされてる
・データソースはMicrosoftAccessに標準添付されてる'NorthWind.mdb'を使う(*2)
*1
なぜかWindows標準のはずのデータベース機能(後述するADO,DAO,ODBCなど)が動かないときもあります。
Windowsのバージョンの違いとかで、Microsoft
Jet データベース
エンジンがインストールされてないってことのようです。
こういう場合にはマイクロソフトのサイトにあるMDAC_TYP.EXEというのを使います。
このファイルはマイクロソフトの提唱技術
MDAC(Microsoft Data Access
Components)そのもので、ADOやら後述するODBCやら、とにかくWindowsからデータベースにアクセスする時に必要になりそうなものが色々パックされて提供されてるものです。
ただMDACにはバージョンが色々あって、ここで対象にしてるJetが含まれているのは2.5までみたいです。(最新は2.8)
うまく動かない人はまずマイクロソフトのダウンロードセンタに行って、”MDAC”で検索し2.5を探してみてください。
*2
'NorthWind.mdb'を使うのは、データソースとしてMDBファイルがたぶんもっとも手軽に用意できそうだからってだけです。
Accessをお持ちでない方はどこかで(どこだ?)何かのMDBファイルを見つけてきて代わりに使ってください。
もし、MicosoftAccessが手元にないときにはMDBファイルをCSVファイルから作成できるありがたいソフトウェア(フリー)があります。
「みっちーのデータベースメンテ for Access 」
■ADO編
のっけからなんですが「ADOとは?」という問いにはまだ満足に答えられません。未熟者です。
それでも一応書くと、、、
最近のWindowsにはデータベースにアクセスする機能が搭載されていて、そういうのは過去にもODBCとかDAOとかがあったんだけど、今はADO(ActiveX
Data
Object)っていうのが流行りっていうかMS推奨。
過去のODBCやDAOも相変わらず使えるんだけど、このADOってのは、それらとの翻訳係になってくれて、インターフェースを統一して一通りのリレーショナルデータベース操作ができる。
いわゆるActiveXによるオブジェクト実装になっていて、何でもかんでもやれメソッドだプロパティだ、で記述する。
と言った感じでしょうか。
↑もうすでに思いっきしまちがってるかも知れません。ご指摘いただいても結構ですが、むしろ阿呆の言ってることと思って、有識者のみなさんは無視を、初心者のみなさんは最初から疑いの目を持ってお読みください。それから(ここ重要)間違っても私に「〜はどうしたらできますか」などの質問を送ってこないように。聞く相手を間違えてます。
【やり方】
まず、いきなりその方法です。以下の記述をお読みください。これだけですぐに実際のプログラミングに入れます。断っておきますが私のオリジナルではありません。元は「2ちゃんねる」上での見知らぬどなたか同士のやり取りで、発言者ご本人がわかれば掲載許諾をいただきたいところなのですが、かの匿名掲示板でのことですので、とりあえず無断で引用させていただいています。もし身に覚えのある方がいらっしゃっればご一報ください。(と言ってもご本人かどうか確かめようもありませんが)なお当時とは状況の変わったところもありますので、若干補足させていただいています。
0.Delphi(のIDE)を起動する 1.メニューのプロジェクト→タイプライブラリの取り込みを選ぶ 2.一覧から、Microsoft ActiveX Data Objects 2.5 Libraryを選ぶ (注:Jetが使えるのは2.5まで、それ以降のバージョンを取り込んで動いたように見えてるのはあなたがラッキーだったから。 一覧に2.5が見つからない人はまずMDAC_TYP.EXEを探しに行こう→下記「なぜかADOが動かないときには」参照) 3.インストールボタンを押す 4.パッケージ dclusr.bplは再構築されますと表示されるので、はいを押す 5.これでADOがコンポーネントに登録される 6.ActiveXタブからConnectionコンポーネントをフォームへ乗せる 7.ボタンを乗せて、そのイベントプロシージャを(下記サンプルコードのように)記述する 以上 |
1.SQL文の実行
mdbファイル'NorthWind.mdb'のテーブル'運送会社'のフィールド'運送会社'を表示させてます。ここでは【やり方】のコーナーにそのまま対応できるようにButton1をクリックする時のイベントプロシージャーとして書いてありますが、この後のサンプルコードは全て単独のプロシージャーないしファンクションとして書きますのでご注意を。動作としてはごくありふれた値の読み出しをするものですが、大抵はこの中のSQLを直すだけで対応できると思います。
変更系SQLの場合は
ADOそのものの使い方が知りたいときには 実際にプログラミングする時には、さらにADOの仕様がわからないとどうにもならないでしょう。その際に ・MSDNのADO APIレファレンス ・タイプライブラリ取り込み時にできるADODB_TLB.pas の2つを参照すれば、手元にマニュアルがなくても大体のことがわかります。 前者は各メソッドやプロパティの意味が、後者からはそれらのdelphiでの書き方がわかります。文法エラーが出たら後者を見てみましょう。 |
2.全テーブル名の取得
SQLそのものにはテーブル名を取得する、という構文がないので、テーブル名を取得するときは何らかのSQLより踏み込んだことをしないとできないはずです。それをADOでやってみました。他の方法でも同じ事を試みてますので比較してみてください。 実行ファイルと同じディレクトリに置かれたNorthwind.mdbの中の全テーブル名をOKを押すたび順番に表示するコードになってます。 このコードではフォームにConnectionコンポーネントを載せてない場合を想定して、あらためてConnection2オブジェクトを生成させてます。 前半は定石の通りだが、後半レコードセットを取得するときOpenSchemaというのを使うのがキモ。このOpenSchemaから色々なシステム上のデータにアクセスできます。 実際に実行してみるとわかりますが、TABLE_NAMEというキーワードで引っかかってくるのは、純粋なテーブルだけでなく、クエリも含まれてます。クエリは全てではなく、どうやらテーブル表示されるものだけ、のようです。純粋なテーブルだけを抜き出したい時には後述のDAOを使った方法のほうがいいみたいです。
MDBファイルをオペレートする話によくMSysObjectsというテーブルを使うといい、という話が出てきます。このMSysObjectsなどはシステムテーブルと呼ばれて、全テーブルとその属性とか処理上有用な情報が入ってます。しかし、このMSysObjectsはユーザの権限のうち「データの読み取り」がデフォルトで不可になってる。 なので今回みたいな目的で使おうと思ったら、この属性をあらかじめAccessなどで変更しておいてやる必要があります。しかも一回読み取りOKにしてやると、なぜか元に戻らなくなったり、使い方が難しくて色々気を使うテーブルみたいです。うーん、あまり有用でないですね。AccessVBAから使うと、そういうこともなく結構便利みたいなんですが...。 |
3.バージョン2.0以降の機能を使うには
ADOにはいくつかのバージョンがあります。前述のMDACのバージョンと対応関係がありますが、どれとどれが対応してるかはよく知りません。 こうしてプログラムを組んでるときは暗黙でADO1.5という古いバージョンを使ってることになってます。だけどADO2.0とかADO2.1とかの新しいバージョンにしかないような機能もあって、例えばここで使ってるGetStringというメソッドもADO2.0以降のレコードセットにしか用意されてないので、ただ普通にコードを書くと「そんなメソッドないよ」とDelphiに怒られてしまいます。 上記はそんな時にレコードセットのバージョンを強引にADO2.0として扱ってしまうやり方です。オープンの仕方なんかも微妙に違うので注意してください。今は大抵のPCでADOは最新になってますのでこれでちゃんと結果が返ってきますが、古いADOのPCで動かすと問題がおきるでしょう。本来であればまずADOのバージョンを確かめるコードを入れて使うべきでしょう。
|
1.SQL文の実行
ADOの1のサンプルコードをDAOでやるとこうなる、って言う例です。ほんとはSQLなんか使わなくてもいろんなDB操作ができるように関数がとりそろえられてるんで、そっち使うべきかも知れませんが。 (1)のクラス文字列が「おまじない」なのが、不安と言えば不安で、他のシステム(=この場合パソコン)でも通用するかどうか保証がないです。実際、Web上で例を探すとここが単に'DAO.DBEngine'となってるケースもありますが、私のシステムでは'.36'をつけないと動作しませんでした。
|
2.全テーブル名の取得
前述のADOでもやった「全テーブル名」の取得のDAO版。TableDefsプロパティのAttributesプロパティが0のものを拾ってます。実際に動かして見るとわかるけど、このページのサンプルの中では、これだけが「いわゆるテーブル」だけを忠実に表示してくれます。他のADOやODBCではだめと判断してはいけません。工夫次第ではうまく行くかも知れません。あくまで未熟な小生がやったらこうなったというだけです。
|
1.SQL文の実行
ふぅ、長かったですね。ご覧の通り、宣言などの前準備がやたらあります。ここでは最低限必要なものだけ書いてますが、使いたい関数や変数、定数が増えるたびに宣言を追加してやらなければなりません。ズルする方法→後述。あと変数の型宣言が全部ODBC独自の型になっていて(PSQLINTEGERとか)、これらが微妙にトリッキーなもんですから(SQLCHARがUCHAR(=BYTE)型だったり)、型チェックにうるさいDelphiでは引数に渡すとき、ちょっと工夫が必要です。strSQLやstrDBの変数の宣言の仕方や(5),(7)での渡し方を見てください。
ODBC関連の宣言でズルをするいい方法 |
2.全テーブル名の取得
ほとんど典型パターン通りですが、SQLの発行の代わりに(1)を使います。結果は(2)で読み出しますが3列目にテーブル名が入ってくるので、第2引数に'3'を指定します。実行結果はこれまたADOともDAOとも違ってまして、システムものも含んだテーブルとクエリのほぼすべてが返ってきます。(1)あたりでパラメータ(特に第4〜7引数あたり)を色々いじるともっとよくなるのかも知れません。 |
3.エラーの診断
一連のODBC関数(SQL〜)はすべてリターンコードを返します。動作に問題がなければSQL_SUCCESS(=0)が返るのですが、何らかの理由でしくじるとSQL_ERRORとかを返します。しかし、リターンコードだけではいったい何が悪かったのか、結構困ります。そんな時は問題箇所の直後でSQLGetDiagRecを呼んでやるとより詳細な情報が得られます。上記のような関数を一個作っておいてデバッグ時に適宜呼んでやるといいでしょう。 呼び方は
|
続編「本格データベースの場合」についても探求してみる
(未着手。書かないかも知れません。と言うかきっと書かないと思います。なぜかって、もうモチベーションがかなり下がってるから。)
MSDE編
MySQL、Firebird、PostgreSQL、Oracle編