開発環境: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に必要な条件は正しくセットされていると思いますが、
なぜヒットしないのかが分かりません。
よろしくお願いします。
質問の仕方が悪いのか、回答が付かないようで。。。
テーブル「AAA」にレコードを追加する際、
同じデータを持つレコードが存在しない場合のみAddNew()→フィールドに値をセット→
Update()をし、
既に同じデータを持つレコードが存在すればAddNew()しないようにするため、
テーブル「AAA」に対して、事前に重複チェックをかけようとしています。
レコードセットに、
SELECT * FROM AAA WHERE [検索条件]”のクエリを渡して検索するやり方だと実行速度
が遅いため、
Seekで試してみようと思った次第です。
Seekは速度的には問題なさそうですが、肝心の検索が上手くいかないようです。
レコードを追加するテーブルが「AAA」で、
かつ検索対象のテーブルも同じテーブルのため、上手くいかないのかなという気がしてい
ますが。。。
Seekに限らず、代替案(できればより高速になるような案)も大歓迎ですので、
ご教授いただきたくお願いします。
m(_ _)m
提示ソース見ただけで実際に試していない回答だけど、↓は関係無い?
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);
> 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 データを作成して渡せ、って事のようだ。
gakさん、返信が遅くなり申し訳ありません。
貴重なご意見ありがとうございます。
ビンゴでした!!
gakさんから教えていただいた通りで動作するようになりました。
逆にこのことを見落としていた自分が恥ずかしいです。
本当にありがとうございました。