私は、CDatabase および CRecordset クラスを使用してデータベース アクセスを行う MFC アプリに取り組んでいます。データベースは、MFC ベースのフォームまたはウィンドウに動的にバインドされません。
レコードの特定のフィールドが NULL であることの検出に問題があります。
私のコードのほとんどは正常に動作しています。データベースへの接続、クエリの発行、レコードの読み取りに問題はありません。ただし、ガベージ文字列を取得しているフィールドがいくつかあり、データベースをチェックすると、問題のフィールドが NULL であることがわかります。
場合によっては NULL が合理的であるため、それを防ぐのではなく、正しく処理するだけのコードが必要です。ただし、問題のフィールドのGetFieldValueから返される値はnull ではありません。有効なポインターではないランダムな値を取得します。どうやら、単純にポインター値をチェックするだけでなく、ある種の NULL のテストを行う必要があるようです。
IsFieldNullと呼ばれるCRecordsetクラスにメソッドがありますが、正しく動作していないようです。または、正しく呼び出していません。この方法がどのように使用されているかについて、オンラインで良い例は見つかりませんでした。ドキュメントには、「フィールドデータメンバー」を指すvoidポインターという単一のパラメーターを取ると書かれていますが、それがどうあるべきかについての定義はありません。ゼロベースのフィールド インデックスが渡される例と、フィールド名を持つ文字列定数が渡される例を見てきました。私はこれらのアイデアの両方を試しましたが、どちらもうまくいかないようです。
実際、CRecordset::IsFieldNull() を呼び出すと、常にコードがネバー ネバー ランドに飛んでいきます。
IsFieldStatusNullと呼ばれる CRecordset の別のメンバーがあり、これはフィールド インデックスを受け取るとされていますが、呼び出しも失敗することがわかりました。
最終的に、私の質問は、CRecordset の特定のフィールドが NULL かどうかをどのように確認するのですか?
既存のコードが質問に関連しているとは本当に思いませんが、リクエストされたので、ここにあります(try / catchブロックを削除するために簡略化されています):
CDBVariant v;
CRecordset theRecordSet(&theDB); // Pointer to my CDatabase object
query.Format("SELECT B.*, B.photographerWebsite AS website FROM gbm_shootphotographers AS A INNER JOIN gbm_photographers AS B ON A.photographerID=B.photographerID WHERE A.shootID=%d;", shootID );
BOOL result = theRecordSet.Open(AFX_DB_USE_DEFAULT_TYPE, query );
memset(&v,0,sizeof(CDBVariant)); // Zero it out before retrieving field
// 1
theRecordSet.GetFieldValue("website", v);
// 2
CString website = *v.m_pstring;
「ウェブサイト」フィールドにデータがあるレコードの場合、問題なく取得されます。文字列は期待どおりです。ただし、「website」が NULL であるレコードの場合、空ではない文字列にガベージが含まれているか、さらに悪いことに、文字列ポインターが正しくありません。率直に言って、NULL の CDBVariant オブジェクトに何かを出力する理由がわかりません。分野ですが、そこに問題があります。
ロケーション #1 とロケーション #2 の両方でIsFieldNullとIsFieldStatusNullを呼び出してみました。どちらにしても雑草の中に消えます。