DAOのSeekについて – プログラミング – Home

通知
すべてクリア

[解決済] DAOのSeekについて


MOON
 MOON
(@MOON)
ゲスト
結合: 23年前
投稿: 8
Topic starter  

開発環境:VC++6.0(MFC)、WindowsXP
使用DB:Access97(DAO接続)

CDaoRecordsetのSeekについて教えてください。

やりたいことは以下です。

(1) セミコロン区切りのテキストファイルを1行ずつ読み込んで、テーブルAAAにINSERT
(2) INSERT前に、テーブルAAAに同様の値を持つレコードが入っていないかをSeekで重複
チェックし、
重複しないレコードのみINSERT

INSERTしたいデータは、必ずテーブルAAAのレコード上に存在するはずなのですが、
(Accessのクエリで確認済み)
Seekで検索を実行すると、常に戻り値が0となり、ヒットしません。

大変長くて恐縮ですが、ソースコードを貼り付けます。
関係なさそうな部分は省略しています。
--------------------------------------------------------------------------------
// DBOpenとレコードセットOPEN(略)

int nCnt = 6;

// Seek用のテーブル定義用領域の確保
CDaoIndexFieldInfo *pIdxFieldInfo = new CDaoIndexFieldInfo[nCnt];
COleVariant *pvarPatam = new COleVariant[nCnt];

CDaoIndexInfo IdxInfo;
CDaoTableDef oTblDef(&oDatabase);

// インデックスとなるフィールド名を設定
// 対象となるのはフィールドBからGまで
pIdxFieldInfo[0].m_strName = _T(DB_NAME_B);
pIdxFieldInfo[1].m_strName = _T(DB_NAME_C);
pIdxFieldInfo[2].m_strName = _T(DB_NAME_D);
pIdxFieldInfo[3].m_strName = _T(DB_NAME_E);
pIdxFieldInfo[4].m_strName = _T(DB_NAME_F);
pIdxFieldInfo[5].m_strName = _T(DB_NAME_G);

// 昇順 or 降順
pIdxFieldInfo[0].m_bDescending = FALSE;
pIdxFieldInfo[1].m_bDescending = FALSE;
pIdxFieldInfo[2].m_bDescending = FALSE;
pIdxFieldInfo[3].m_bDescending = FALSE;
pIdxFieldInfo[4].m_bDescending = FALSE;
pIdxFieldInfo[5].m_bDescending = FALSE;

// インデックス名
IdxInfo.m_strName = _T(strIndexName);
// インデックスを付与するフィールド数
IdxInfo.m_nFields = nCnt;

// インデックスを付与するフィールド名
IdxInfo.m_pFieldInfos = pIdxFieldInfo;

oTblDef.Open(_T(Car_Log_Table));
oTblDef.CreateIndex(IdxInfo);

/****************************************/
/* 一時ファイルの読み込みとレコード追加 */
/****************************************/
// 書込み用のレコードセット作成とOPEN
rsWrite.Open(dbOpenDynaset, AAA, dbAppendOnly);

char cReadBuff[128];
CString strRead;
int nPosColon;

for (nRecCnt = 0; nRecCnt < nRecMax; nRecCnt++) {

// セミコロン区切りのファイルはOPEN済み
// 1行ずつ読み込み、
// セミコロンで区切った各フィールドをそれぞれ変数に格納
<中略>

// 重複レコードを検索
// フィールドBからGまでの値が重複しているかをチェック
// 検索用のレコードセットをOPEN
rsFind.Open(dbOpenTable, _T(Car_Log_Table), dbReadOnly);

rsFind.SetCurrentIndex(strIndexName);

COleVariant var1(strB);

// strBは日付時刻型に変換する
COleDateTime varDT;
varDT.ParseDateTime(strC);
COleVariant var2(varDT);

COleVariant var3((long)nD);
COleVariant var4(strE);
COleVariant var5(strF);
COleVariant var6(strG);

pvarPatam[0] = var1;
pvarPatam[1] = var2;
pvarPatam[2] = var3;
pvarPatam[3] = var4;
pvarPatam[4] = var5;
pvarPatam[5] = var6;

// 重複データをSeek
bIsOverlapped = rsFind.Seek(_T(=), pvarPatam, nCnt);
rsFind.Close();

if (!bIsOverlapped) {

rsWrite.AddNew();

// レコードセットのフィールドにAppendする値を入れる処理
<中略>

// レコードに重複なしでINSERTする
rsWrite.Update();

// Validカウンタ表示を更新
nValidCnt++;

nAddedCnt++;
}
else {
// Overlappedカウンタ表示を更新
nOverlapCnt++;

bIsOverlapped = 0;
}
}
--------------------------------------------------------------------------------

Seekに必要な条件は正しくセットされていると思いますが、
なぜヒットしないのかが分かりません。

よろしくお願いします。


引用未解決
トピックタグ
MOON
 MOON
(@MOON)
ゲスト
結合: 23年前
投稿: 8
Topic starter  

質問の仕方が悪いのか、回答が付かないようで。。。

テーブル「AAA」にレコードを追加する際、
同じデータを持つレコードが存在しない場合のみAddNew()→フィールドに値をセット→
Update()をし、
既に同じデータを持つレコードが存在すればAddNew()しないようにするため、
テーブル「AAA」に対して、事前に重複チェックをかけようとしています。
レコードセットに、
SELECT * FROM AAA WHERE [検索条件]”のクエリを渡して検索するやり方だと実行速度
が遅いため、
Seekで試してみようと思った次第です。

Seekは速度的には問題なさそうですが、肝心の検索が上手くいかないようです。

レコードを追加するテーブルが「AAA」で、
かつ検索対象のテーブルも同じテーブルのため、上手くいかないのかなという気がしてい
ますが。。。

Seekに限らず、代替案(できればより高速になるような案)も大歓迎ですので、
ご教授いただきたくお願いします。

m(_ _)m


返信引用
gak
 gak
(@gak)
ゲスト
結合: 21年前
投稿: 132
 

提示ソース見ただけで実際に試していない回答だけど、↓は関係無い?
http://support.microsoft.com/kb/140599/en-us
VC6って事はデフォルトは !UNICODE だろうし可能性はありそう。

要するに、COleVariant に文字列が渡された場合
0、!UNICODE なので LPCTSTR は ansi。
1、COleVariant内部で SysAllocString() 使って文字列コピーする。
2、SysAllocString() は UNICODE 文字列を要求(!16Bitアプリ時)する。
4、COleVariant var1(_T(文字列));
ってした場合、_T(文字列) は ansi系文字列。
5、SysAllocString() に ansi 文字列を渡す事になり不正な結果に。
ってなってるんじゃ無いかと。

> COleVariant var1(strB)
上記が原因なら、先に挙げたページを見る限りこうしてやれば良さげ。

// COleVariant var1(strB)
COleVariant var1(strB, VT_BSTRT);


返信引用
gak
 gak
(@gak)
ゲスト
結合: 21年前
投稿: 132
 

> http://support.microsoft.com/kb/140599/en-us
> 5、SysAllocString() に ansi 文字列を渡す事になり不正な結果に。
> ってなってるんじゃ無いかと。
違うわ。
SysAllocString() に渡す前に UNICODE 変換してるみたいだから問題無いや。

単純に !UNICODE 環境での CDaoRecordset はANSI文字列を扱う。
だが、
> COleVariant var1(_T(文字列))
とすると VT_BSTR(UNICODE)の文字列データが出来上がってしまう。
それを CDaoRecordset に 渡してもマルチバイト文字じゃないので扱えない。
だから、VT_BSTRT(ANSI)の VARIANT データを作成して渡せ、って事のようだ。


返信引用
MOON
 MOON
(@MOON)
ゲスト
結合: 23年前
投稿: 8
Topic starter  

gakさん、返信が遅くなり申し訳ありません。

貴重なご意見ありがとうございます。
ビンゴでした!!

gakさんから教えていただいた通りで動作するようになりました。
逆にこのことを見落としていた自分が恥ずかしいです。

本当にありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました