Windows2000(SP4)
Delphi6 Personal
Delphiの質問にはならないかと思いますが、よろしくお願いします。
csvのデータを元に、Access97のMDBに対して、Insert+Update更新を
行なうプログラムを作成しています。
※CSVとMDBの項目レイアウトは同じという前提。
※DAO3.6を使用。
Access97のMDBで作成されたテーブルのキー情報を取得して、
update文のwhere句を生成しようとする箇所で悩んでいます。
キー項目となるフィールドの名称はキーインデックスから取得できるのですが、
そのキー項目が、データフィールドのどの位置なのかを知ることができれば
CSVとMDBの項目位置が対応しているハズなので、where句が生成できると
考えています。
取得方法ありましたら教えて下さい。
補足です。
キーフィールドとデータフィールドを、ループさせながら「.Name」で
比較する以外に何か方法はありませんか。
例えばメソッド一発発行で取得できるとか?
そのまま
FieldByName
で対応できますが、それでは何か問題があるのでしょうか?
>HOtaさん
「FieldByName」ですが、フィールド名を引数に指定して、フィールドの値を
取得するものではないでしょうか?
フィールドの値ではなく、フィールドの位置番号が知りたいのです。
例えば、
> objDB.objTBL[TBLNAME].Fields[i].Value
といったある項目の値を取得する場合の
iの値です。
処理イメージとしては、、、
CSVの内容を元に、MDBデータの更新をかけます。
1)まずcsvレコードを1件読みます。(カンマは分解して配列化)
2)csvレコードの内容から既存データが存在するか?select文を発行します。
3)既存しなければinsert発行処理
4)既存すればupdate文発行処理
5)項1〜4をCSVデータを読みきるまで繰返し
sqlを発行するときのwhere句を生成しようとした場合に、
> var wk : string
> for i := 0 to objDatabase.TableDefs[PDt].Indexes['PrimaryKey'].Fields.Count - 1 do
> begin
> //項目名表示
> wk := objDatabase.TableDefs[PDt].Indexes['PrimaryKey'].Fields[i].Name
> end;
で、変数wkに項目名が入ります。
仮にキー項目が3つあったとしたら、プライマリキーのフィールド番号は
0、1、2と格納されます。
項目名に続く条件値をCSVから取得するのですが、CSVはカンマで区切って
配列に入れるので、MDBのデータフィールドと並びは同じハズです。
※という前提でお願いします。(^^;
しかしインデックスから読み取れるキーフィールド番号と
データフィールド番号が必ずしも一致しているとは限りません。
CSV側のデータ上で、キー項目となる位置を特定したいのです。
いかがなものでしょうか。実現可能でしょうか。
追記しようとして間違えて送信ボタンを押してしましました。
select * from ○○TBL
where ((項目A = 100) and (項目B = "あああ"));
^^^^^^ ~~~ ^^^^^^ ~~~~~~
^^^^^←キーインデックスのフィールド名から取得
~~~~~←MDB側から何らかの手法でフィールド位置を特定、添え字とし、
配列に格納されたCSVデータのキー項目を、添え字を使って
値を取得
このような感じをイメージしています。
SELECT文でFieldの物理データベーステーブル内での位置ならば、
FieldByName('インデックスフィールド名').FieldNo
でインデックスフィールドの順番が解ると思います。
>HOtaさん
FieldNoの件、ありがとうございます。
試してみましたが、相変わらずOleExcptionが発生します。
何かオブジェクトの指定方法など根本的な部分が間違っているように
思いますが、ネット検索でもあまり事例がないようです。
リファレンスなど解説していただいているサイトなどご存知ないでしょうか?
> CoInitialize(nil);
> objDBEngine := CreateOleObject('DAO.DBEngine.36');
> objWorkSpace := objDBEngine.Workspaces[0];
> objDatabase := objWorkSpace.OpenDatabase(PDm,False, False);
> objTableDef := objDatabase.TableDefs[PDt];
> //objRecordset := objDatabase.OpenRecordset('SELECT * FROM ' + PDt); //(3)
>
> //キー情報の組立
> for i := 0 to objDatabase.TableDefs[PDt].Indexes['PrimaryKey'].Fields.Count - 1 do
> begin
>
> wk := objDatabase.TableDefs[PDt].Indexes['PrimaryKey'].Fields[i].Name;
> showmessage(wk);
> //ここまではOK。フィールド名は正しく格納できる。
>
> //showmessage(objDatabase.TableDefs[PDt].Indexes['PrimaryKey'].Fields[i].FieldNo);
> //showmessage(objRecordset.FieldByName[wk].FieldNo);
> showmessage(objDatabase.TableDefs[PDt].FieldByName[wk].FieldNo);
↑ここでOleException。
FieldByNameをサポートしていないと表示。
>
> end;
>
> //いろいろ閉じる
> objDatabase.Close;
> objWorkSpace.Close;
> CoUninitialize;
>
> //終了
> halt(RC);
>
FieldByNameは関数ですから、[]ではなく、
()で引数を呼んでください。
Delphi の TDataset から派生したクラスを使っているわけでは無いので
FieldByNameメソッドは存在しません。
>キーフィールドとデータフィールドを、ループさせながら「.Name」で
>比較する以外に何か方法はありませんか。
>例えばメソッド一発発行で取得できるとか?
Access側でサポートしていないのであれば、
Nameプロパティで比較するしかないのでは?
そうですね。TADOコンポーネントと間違えていました。
>HOtaさん、Basserさん
調べてみましたが他に手はないようなので、
Nameプロパティで比較するようにしてみます。
ありがとうございました。
DAOを使っているなら、ADOを使ってみれば如何ですか?
これならTDatasetが使えるので、簡単ですよ。
ツイート | ![]() |