真琴


データベースへの接続  2003-07-23 01:56:33  No: 4183

最近、VBからDelphiへ乗り換えたばかりで
VBとはかなり違うので四苦八苦しています。

VBより遥に難しいですね(^^;

フォームにデータグリッドを貼り付けて、
ADOで外部データベース(MS-ACCESS)
に接続してテーブルの内容をデータグリッドへ
表示させてみたいのですが、下記の
VBと同様にDelphiに読み替えれば良いのでしょうか?

細かいところが分らずどう書き換えればよいか
わかりませんで、投稿させて頂きました。

また、Delphiにも参照設定(ADO)ができるのでしょうか?
どこで設定できるのでしょうか?

Private Sub Form_Initialize()
    
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset

    cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strPathName & "\sample.mdb;"
    rs.CursorLocation = adUseClient
    rs.Open "select * from tbl_sample", cn, adOpenStatic, adLockOptimistic
       
    Set dtgrid_sample.DataSource = rs

End Sub


にしの  2003-07-23 03:04:26  No: 4184

名前の欄と、タイトルの欄が逆ですよ^^;

VBとDelphiは、よく比較されますが、同じコードを簡単に書けるわけではありません。
その場合、VBのコードを(構造を変更せずに)Delphiに書き換えるのも、Delphiのコードを(構造を変更せずに)VBに書き換えるのも、同じくらいに難しい物です。
比較されるのは、コンポーネントの利用の場合の簡略化ですね。
DBの設定をコンポーネントのみで完結できます。
# 細かい部分はコーディングが必要です

Delphiでは、

  cn := CreateOleObject('ADODB.Connection');
  rs := CreateOleObject('ADODB.Recordset');

  cn.Open('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=' + strPathName + '\sample.mdb;');
  rs.CursorLocation := 3;
  rs.Open('select * from tbl_sample', cn, 3, 3);

こんな形でしょうか。
定数が全て3になっているのは偶然です。
検索して見つけた値が全て3だっただけで。
# 動作は未確認です

Delphiは、参照設定の必要はありません。
OCXが登録されていれば、そこから探します。


真琴  2003-07-23 17:52:29  No: 4185

にしのさん、お返事ありがとうございます^^

早速、このようなコードで試してみたのですが、
このような場合、Delphiではcn、rsはobject型
としてみたのですが、これがコンパイル通らないようです、
お手数ですが引き続きフォローのほど宜しくお願いします。

procedure TForm1.FormCreate(Sender: TObject);

var
  cn: object;
  rs: object;

begin

  cn := CreateOleObject('ADODB.Connection');
  rs := CreateOleObject('ADODB.Recordset');

  cn.Open('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\sample.mdb;');
  rs.CursorLocation := 3;
  rs.Open('select * from tbl_sample', cn, 3, 3);

  DBGrid1.DataSource := rs

end;


真琴  2003-07-23 18:27:58  No: 4186

失礼しましたobject型ではななく
olevariant型にするようですね。

しかしながら、cn := CreateOleObject('ADODB.Connection');
この行でコンパイルエラーです、CreateOleObjectの
識別子が未定義ですと言われます。

これはVBでいうところのライブラリが無い状態ですよね?

ADOだけでやってしまおうと思っているので、
フォームにデータグリッドだけしか配置していませんが、
他にもADOのコンポーネントが何か必要なのでしょうか?


にしの  2003-07-23 20:18:06  No: 4187

このあたりは、バージョンを示していただかないと。

バージョンによっては、CreateOleObjectでなく、CreateObjectの場合もあります。

ADOコンポーネントは、確かDelphi6かDelphi7からついていますね。
これを使えば簡単にできるかもしれません。
ADOのデータグリッドを使わないで、CreateOleObject(CreateObject)で作成する場合は、データの格納もコードで書く必要があります。

ADOコンポーネントがない場合は、
http://home1.infonia.ne.jp/~delphian/delphi/
などでADO対応コンポーネントを探してみてください。

ちなみに、「ライブラリがない状態」ではありません。
関数が定義されていない、文字通り(識別子が未定義)の状態です。


真琴  2003-07-23 21:52:33  No: 4188

にしのさん、お返事ありがとうございます^^

失礼しました、ちなみにDelphi 6 Proffesionalでした。

ただ、ADOで書けばデータグリッドひとつあれば
可能だということですよね?

>ADOのデータグリッドを使わないで、CreateOleObject(CreateObject)で作成>する場合は、データの格納もコードで書く必要があります。

これは使いたくないです、それはVBと同じですね。

そうでしたADODOB.Connectionではなかったでした、
CreateOleObjectでした(^^;

CreateObjectでもダメでした。
どうしてなのでしょうか?

もし何か考えられる要因がありましたらご指導下さい。


にしの  2003-07-23 22:41:06  No: 4189

何か勘違いされていると思いますが、Delphiのコンポーネントはライブラリ不要ですよ。
# オプションを変更した場合は、DLLが必要になります
直接CreateObjectしても、ADOをインストールしていないPCでは動きません。

> ただ、ADOで書けばデータグリッドひとつあれば
> 可能だということですよね?
ADOで書く、というのが、ちょっとわかりませんが、コーディングで、ということでしょうか。
コーディングで書くのなら、DBGridでなくTStringGridなどで1つずつ格納してやる必要があるということです。

> >ADOのデータグリッドを使わないで、CreateOleObject(CreateObject)で作成
> >する場合は、データの格納もコードで書く必要があります。

> これは使いたくないです、それはVBと同じですね。

「これ」が、ADOのコーディングをがしがし書くのが嫌なのか、ADOコンポーネントを使用するのが嫌なのかどちらでしょうか。
僕としては、VBを使うこと自体躊躇しますので、VBとDelphi、どんなものを作ろうと、Delphiを推します。

CreateOleObjectですが、uses節に
ComObj
を追加してみてください。


真琴  2003-07-23 23:16:21  No: 4190

にしのさん、お返事ありがとうございます。

>何か勘違いされていると思いますが、Delphiのコンポーネントはライブラリ不要ですよ。

いえっ、勘違いも何も(^^;
まだDelphiを使いはじめて数時間程度しか触っていないので
何も分らないことだらけです。

Delphi自体でADOのライブラリを持っているから
VBと違ってそのまま使って良い訳ですね?

でも、それが使えていないからこのようなエラーになって
いる訳ですよね?

>ADOをインストールしていないPC

PCにインストールというのはどういう事でしょうか?

現在、VBがインストールされていますので
共有ライブラリ(DLL)でADOがDelphiで使えても
良いという事ではないのですか?

>コーディングで書くのなら、DBGridでなくTStringGridなどで1つずつ格納してやる必要があるということです。

TStringGrid、これを使うんですね。

VBではDBGridを使ってコーデイグしていたので
DelphiのDBGridがVBのそれと同じなのかと思っていました。

TStringGrid、これを使ってみます。

というのは、ADOの何も考えないで使える
コンポーネントを使うことが嫌だという意でした。

ランタイムのいらないEXEが作れないので
VBはあんまり使ってはいなかったのですが、
DB接続したりする程度には便利でしたので
時々使っていました。

こからDelphiの素晴らしさを体験したいです。

>CreateOleObjectですが、uses節に
>ComObj
>を追加してみてください。

これもダメでした(>_<)


にしの  2003-07-24 00:37:53  No: 4191

> Delphi自体でADOのライブラリを持っているから
> VBと違ってそのまま使って良い訳ですね?
いや、DelphiがADOのライブラリを持っているわけではありません。
ADOライブラリは、Microsoftが提供しています。
これの利用方法の問題です。
Delphiで作成した、ADOでDBを操作するアプリケーションを作成しても、Microsoft ADO Libiraryが入っていないマシンでは動きません。
これは理解していますか?

> でも、それが使えていないからこのようなエラーになって
> いる訳ですよね?
いえ、そこまでもたどり着いていません。
ADOが入っているかどうかすらDelphiが知る前に、エラーが起きています。
ADOが入っていない場合、CreateObjectでnullを返すか、何らかの例外を発生します。
CreateOleObjectの識別子うんぬんは、コンパイラが出しているので、実行はしていませんよね。
ADOが入っているかどうかは、実行してから判断します。

> というのは、ADOの何も考えないで使える
> コンポーネントを使うことが嫌だという意でした。
なるほど。
コンポーネントを利用しない場合でも、そのコンポーネント同等の機能を実装しなければなりませんよね。
すでにあるコンポーネントは、それなりにデバッグがされていて、使える状態にあります。
デバッグ済のコンポーネントを使用しないで、自作した場合は、この機能に関してもデバッグする必要が出てきます。
つまり、
コンポーネントを使用する場合
メリット:開発効率が上がる
デメリット:必ずしも、実現したいことと一致するとは限らない

コンポーネントを使用しない場合
メリット:自分の思い通りの機能を実装することができる
デメリット:開発効率が落ちる

となります。自力で作成できない機能は、思い切ってコンポーネントを利用することも手です。
# これは、ポリシーにもよるかと思いますが

> これもダメでした(>_<)
Delphi6であれば、ADODBというユニットが使えます。
ADODBをuses節に追加すれば、

TADOConnection
TADODataSet
が使えると思います。
ヘルプで、「ADO データセットの使い方」を参照してください。
また、Professionalならば、ソースが付いているはずなので、ADODB.pasやADOInt.pasを参照してください。
ADODB.pasが理解できないのであれば(初心者だからとでなく)、あきらめてコンポーネントを使用した方がよろしいかと思います。
結局、ADODB.pasと同じような処理が必要になりますので。


真琴  2003-07-24 01:44:15  No: 4192

にしのさん、お返事ありがとうございます。

失礼しましたm(__)m

uses節にComObjを追加し
CreateOleObjectでコンパイルが通りました。

CreateObjectにしていました(^^;

>Delphiで作成した、ADOでDBを操作するアプリケーションを作成しても、>Microsoft ADO Libiraryが入っていないマシンでは動きません。
これは理解していますか?

ハイ、それなら理解できます。

>となります。自力で作成できない機能は、思い切ってコンポーネントを利用することも手です。
># これは、ポリシーにもよるかと思いますが

ちょっといい過ぎでした(^^;

例えば、接続情報文字列を指定してDBへ接続し、
取得したレコードセットをデータグリッドへを代入したり、
レコードの移動とか、コンボ等のRowSorceの設定
程度の簡単な処理は、わざわざコンポーネントなどを
使わずにコーディングしたいなと思っていたのでした。

もう少しよろしくお願いします。
やっとデータグリッドへの表示まできました。
イメージではこんな感じでできるではないかと思い
試してみました、Googleを漁っても答えがみつかりません。

  DBGrid1.DataSource:=rs;  ←ここでコンパイルエラー
  DBGrid1.Columns(0):=rs.Fields[id];
  DBGrid1.Columns(1):=rs.Fields['name'];

それから、インスタンスの解放なのですが、
VBでは慣れた記述もDelphiでは引っかかります(^^;

rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin

//インスタンスの解放

end;

end.

重ね重ね、宜しくお願いします。


にしの  2003-07-24 06:14:32  No: 4193

> もう少しよろしくお願いします。
> やっとデータグリッドへの表示まできました。
> イメージではこんな感じでできるではないかと思い
> 試してみました、Googleを漁っても答えがみつかりません。

前にも書いたとおり、コンポーネントを使用しないのであれば、TStringGridなどに「コーディングで」データを格納する必要があります。
TStringGridであれば、Cellsプロパティを参照してください。
コーディングで行うならば、TDBGridは使えません。

どうしても使いたい場合は、TCustomDBGridを継承し、CreateOleObjectで作成されたオブジェクトからデータを取得するようなコンポーネントを作成してください。
もちろん、TCustomDBGridでなく、TCustomControlから継承し、自前で描画するというのも手ですし、RegisterClassExでウィンドウクラスを定義して、それをCreateWindowExで作成するのも手です。
結局は、ADOコンポーネントと、DB関連のコントロールを作成することになります。
# なので、前に、「結局、ADODB.pasと同じような処理が必要になりますので」と書きました

オブジェクトの解放は、通常はFreeプロシージャを使います。
OleVariantの場合は、Unassignedを代入するだけだったと思います。

rs.Close;
cn.Close;
rs := Unassigned;
cn := Unassigned;

こんな感じだと思います。
# 未確認です


真琴  2003-07-24 17:56:10  No: 4194

にそのさん、お返事ありがとうございます。

>TCustomDBGridを継承し、CreateOleObjectで作成されたオブジェクトからデ>ータを取得するようなコンポーネントを作成してください。

VBのDBGrid違って取得したレコードセットを代入できないんですね。
具体的にはこれができるようなコンポーネントを自作するという理解
で良いでしょうか?

継承ですかぁ、本当にオブジェクト思考なんですねDelphiって、
大学時代以来なのでもうどんな使うのか忘れてしまいました。

継承するという事は、関数やメソッドを定義したり、オーバライドしたり
するのでしょうけれでも、具体的には、CreateOleObjectで
作成されたオブジェクトからデ>ータを取得するような機能とは
どのように考えれば良いでしょうか?

また、こうしたDelphiの技術情報などを提供されている
サイトなどありましたら併せて教えて頂けましたら幸いです。


OKA  2003-07-24 18:16:07  No: 4195

http://wblue.web.infoseek.co.jp/
でお勉強。


にしの  2003-07-24 18:25:21  No: 4196

まず、
http://www.borland.co.jp/delphi/papers/ado/ado02.html
これを見てください。
ADOコンポーネントを使用した場合、このようになります。

このとき使用するコンポーネントは、
TADOConnection
TADOTable(もしくはTADOQuery)
TDataSource 
TDBGrid
となります。

具体的には答えられませんが(DBコントロールを作るのはかなり面倒なので)、
・DBのメタデータよりフィールド名・種類などを取得
・DBのレコードデータよりデータを取得
などが、DBからデータを取得する部分。
・フィールド名の表示
・データの表示
などが、表示部分。
・DBに対してInsert/Update/Delete
・それに伴う、表示の更新
などが、DB更新時の処理。
となります。
細かい部分は省いています。

こうした情報は、ソースを読むとよいですよ。
かなり勉強になります。
あとは、他人の作ったコンポーネントのソースを読みましょう。
自分の知らないテクニックがたくさんあると思います。

ホームページとしては、Delphi-MLの過去ログでしょうか。
http://www2.big.or.jp/~osamu/Delphi/
ここから、ダウンロードや検索ができます。


真琴  2003-07-25 00:08:07  No: 4197

OKAさん、お返事ありがとうございます。

早速、参考リンク拝見させて頂きました、
コンポーネントの作成の方法が解説されいて
とても勉強になりそうです。

にしのさん、お返事ありがとうございます。

>ADOコンポーネントを使用した場合、このようになります。

そうなんですよね、私もこれ見ました。
で、たったこれだけのことでこんなにもコンポーネントを
ぺたぺたと貼り付けるのは面倒で嫌だなと思ってのことでした。

TCustomDBGridこれですが、
単純にオブジクトを参照するところだけ作ってあげれば
表示・更新の処理は継承先のTCustomDBGridの機能を
使えると考えていました。

甘かったですね(^^;

表示部分も作る必要があるんですね、それに、
更新の時の処理も作成する必要もあったとは。

これは想像を遥に超えていました。

逆に苦労しても入り口で頑張って勉強しておけば
良い経験にもなりそうでうね、途中で挫折しそうな気も
しますが(^^;

Delphi-MLの過去ログあたりも検索してみてはいるのですが、
DBGridにレコードセットが代入できないのであれば、
探していたものがどうりで見つからない訳ですね。

>あとは、他人の作ったコンポーネントのソースを読みましょう。

これが一番勉強になりそうですね^^

独学でやっているので誰かのかのサンプルを真似て
動かしてみるしか良い方法が見つからなくて、
すべてそうしてきました。

もし、コンポーネントのソースを公開されているような
ところをご存知でたら、また、併せて教えて下さいませ。


にしの  2003-07-25 00:19:25  No: 4198

ODBC Access for Delphiがよろしいかと思います。
http://homepage1.nifty.com/TAK
ここに、単方向DataSetのサンプルがありました。
ODBCコンポーネントを使用する形ではありますが、参考になるかと思います。
# このコンポーネント、前はソースがなかったのですが、今はどうなんでしょうね


XOOX  2003-07-25 09:23:02  No: 4199

最近自前データベースしかやってないので正確にはかけませんが
スレッドの展開があまりにもひどすぎるのでレスをさせてもらいます。
まず根本的な勘違いとして
delphiで出来ないことを質問しているのに対して
質問とは別方向の答えをしているように思います。
この件の質問はActive-Xの扱いに対するdelphiの柔軟性の無さの典型例です。

delphiでDatabaseをやる場合基本的にはボーランドの作ったものは使わないほうが良いし
又ODBCなんてのは前世紀の遺物なので論外です。

ADOかDAOを使う場合は典型的なdelphiプログラマーなら
Torryあたりでコンポーネントを探すのが良いと思います。
http://www.torry.net/db_msother.htm

でここからが本論です。
delphiでADOを使う場合、
まず最初にすることは「タイプライブラリー」の取り込みをする
ことです。
そうすると「ADODB_TLB.pas」と言うのが作られます。
メインプログラムではコンポーネントを貼り付けないで
uses節でADODB_TLBを追加します。
この方法はdelphi3,4用として紹介されていたもので
現段階でも
http://homepages.borland.com/ccalvert/TechPapers/Delphi/ADOBasics/ADOBasics.html
あたりにありますが
取り込むADOのバージョンによって宣言方法が違うらしいので
その辺はADO自体についてしらないとだめだと思います。
但し、この方法は結果的にVBライクになりかつ脱VCLや
FreePascal等への移行も容易ですが
コマンド志向が強く、下層プログラマー向きです。
VBのことは良く知りませんが使用宣言して
ADOに対してコマンドを送るような方法をとっていたのなら
多分この方法がベストだと思います。

ADO関連のコンポーネントはシェアウェアが多いようです。
やはり上記のTorryあたりでソースつきコンポーネントでは
そのままビルドできるかわかりませんが
AOADODBというのとnpadoというのはソース付です。
Tdatasetを前提としているようですが
作成済みのTLBファイルなどもあるので
タイプライブラリーでの取り込みミスを避けられると言うメリットもあります。
とりあえずダウンロードしてソースを眺める意義はあると思います。
大量のソースのほとんどは宣言文(GUIDなど)でプログラム自体は少ないです。

根本的にADOを使ったプログラミングに関しては
VBを持っているのならdelphiを使うのは避けたほうが良いように感じます。

いっそのことActiveXコンテナーみたいなものをアプリケーションに持たせるのも手です。
例えばIEのActive-Xをタイプライブラリーないしはコントロールとして使用すると
スクリプトでいきなり任意のActive-Xを使えます。
速度はODBC並みに遅くなると思いますが...

発言内容は不正確かつ無責任ですがとりあえず参照URLなどを載せることで
勘弁してください。
私自身はデータベースはベタのファイルアクセスとWinsockベースのサーバークライアントでやる形で
データベースのファイル自体はDbase3あたりを準拠にしています。


XOOX  2003-07-25 09:31:45  No: 4200

すみません。
上のレスは
CreateOleObject
をよく理解していないで書いたものでdelphi3-5用です。
申し訳ありませんでした。


真琴  2003-07-25 20:52:24  No: 4201

お返事が遅くなりましたm(__)m

にしのさん、ありがとうございます。

これを頼りにその他参考リンクを勉強させて頂いて
自作コンポーネントを作ってみたいと思います。

XOOXさん、ありがとうございます。

Delphi 6のCreateOleObjectでは先の投稿は無視して下さい
という事でしょうか。
とんでもございません、そんなこといわれると恐縮です(^^;


XOOX  2003-07-25 21:52:55  No: 4202

フォローです。

私なりに調査した結果
CreateOleObjectを使うと画期的に速度が遅くなることがわかりました。
(ちなみにdelphi2から可能)
http://www.borland.co.jp/delphi/papers/servers/servers1.html  
など

やはりdelphiの場合はタイプライブラリーを取り込むほう方法がベストのようです。
但し私なりの心象としてはスクリプトベースの
データベースコンバータを作る場合CreateOleObjectを使う形にすれば
どんなデータベースにでも対応できるので手法としてはありだと感じました。

いまからはじめる場合はまとめると
ODBC                    ×
CreateOleObject        ×
DAO                    △
ADOのコンポーネント    ○
タイプライブラリー取込  ○
ということのようです。

しかし考えてみるとdelphi自体のタイプライブラリーの取り込みを
動的に行えばよいのかなぁと感じつつある今日この頃。

まぁとりあえず動くものを作るルートはいくらでもあるので
とりあえず一旦形にするのも良いことだと思います。
私もこれを機にADOを数パターン作ってみようと思います。
(exeサイズは100kbyte程度)

役立ちそうなアドバイスとしては
「イニシャライズなどのパラメータはコードに組まず
プロパティないしは外部読み込みにしたほうが良い」
とだけはいえます。


真琴  2003-07-25 22:33:53  No: 4203

XOOXさん、フォローありがとうございます。

>やはりdelphiの場合はタイプライブラリーを取り込むほう方法がベストのようです。

これなのですが、具体的にはどのようにするのでしょうか?
Delphi6でのことではその限りではないのかなと思い、
そこはさらっと読んでしまいました。

それから、もうひとつ教えて下さい。

>「イニシャライズなどのパラメータはコードに組まず
>プロパティないしは外部読み込みにしたほうが良い」

これは具体的にはどういう事でしょうか?

VBでもLaod時やInitialize時にDBを読み込むようにして
いましたので迷わずDelphiでもそうしたのですが、
これの事でしょうか?

Initialize時のvar cn olevariant, var olevariant rs
という宣言は、その後、Interface部での宣言に移しましたが、
もしこの事でしたら修正してあります^^


OOHirosi  2003-08-20 03:45:34  No: 4204

Delphiの場合は、もっと簡単ですよ。D6 Pro版ならADOコンポーネントが入っていると思います。

最初にADO頁のTADOConnectionをフォームに張りつけます。
右クリックして[ConnectionStringの編集]を選択します。
[接続文字を使う]のビルドボタンを押すと[データリンクプロパティ]が出ますので、プロバイダ・接続のデータベース名の設定をして、接続のテストでOKなら接続の設定は終わりです。

次に同様にTADOQueryを張りつけて、Connectionプロパティをドロップダウンして、先程のTADOConnectionの名前を設定します。SQLプロパティにSQL文を設定します。

次にData Access頁のTDataSorceを張りつけます。DataSetプロパティをドロップダウンしてADOQueryを設定します。

最後にDataControls頁のTDBGridを張りつけます。上記の3つは実行時には見えなくなりますが、TDBGridだけは見えます。Alignプロパティを帰るとフォームのサイズに合わせて変化します。DataSorceのプロパティをドロップダウンしてDataSorceを選びます。

ここまでで画面の設定は一応終わりです。試しにTADOConnectionのConnectプロパティをTrueにして、ADOQueryのActiveプロパティをTrueにしてみてください。SQL文が正常ならレコードの中身が表示されます。

プログラムはボタンを足したりして、オブジェクトインスペクタのイベント頁のOnClickなどをダブルクリックすると自動でイベントが作成されそこに書きます。
この場合は、デッバッグ状態と設計状態の2つがデータベースにアクセスしようとするので、
    ADOConnection1.Connection := false;
    ADOConnection1.COnnection := true;
    ADOQuery1.Close;
    ADOQuery.Open;
で実行できると思います。読むと長いようですが、これだけの操作でこの場合はAccessですが、Oracleだって同じように操作できます。

要するに、Connection->Dataset->Dataseoece->DataControlが組です。このままで編集が出来ます。途中のDataSetから内容を読み出して、StringGridやEditなどに表示して編集すると、またプログラムでDatsetに値を入れてPostするようなプログラムを書きます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加