次の方法で共有


レコードセット: データ列を動的に結びつける方法 (ODBC)

このトピックの内容は、MFC ODBC クラスに該当します。

通常、レコードセットとテーブル列は、デザイン時に結びつけられます。しかし、場合によっては、開発時に確定できない列と結びつける必要もあります。 このトピックでは、次の内容について説明します。

  • 列とレコードセットを動的に結びつける必要性

  • 実行時に列を動的に結びつける方法

注意

このトピックの内容は、バルク行フェッチが実装されていない CRecordset の派生オブジェクトを対象にしています。 バルク行フェッチを実装しているレコードセットには、ここで説明する方法を基本的に使用しないことをお勧めします。 バルク行フェッチの詳細については、「レコードセット : バルク行フェッチ (ODBC)」を参照してください。

列を動的に結びつける必要性

デザイン時に、MFC アプリケーション ウィザード または MFC ODBC コンシューマー ウィザード (クラスの追加から使用) によって、データ ソースの既知のテーブルおよび列に基づいてレコードセット クラスが作成されます。 しかし、後になってデータベース内の列またはテーブルが変更されることがあります。 つまり、アプリケーションが実行される時点でテーブルや列が追加または削除されることがあります。 すべてのデータ アクセス アプリケーションでこのような問題が発生するわけではありませんが、発生した場合は、再デザインまたは再コンパイル以外の方法で、データベース スキーマの変更に対応する必要があります。 このトピックでは、その方法について説明します。

ここでは、列を動的に結びつける最も一般的なケースについて説明します。これは、既知のデータベース スキーマに基づいて作成されたレコードセットで、実行時に追加された列を処理する方法です。 追加された列は、最も一般的なデータ型である CString 型フィールド データ メンバーに割り当てられるものと想定します。その他のデータ型については、ヒントを示します。

コードを多少変更するだけで、以下の機能を追加できます。

  • 実行時に利用可能な列を判定する

  • 実行時に追加された列をレコードセットに動的に結びつける

レコードセットには、プログラムのデザイン時にわかっていた列に対するデータ メンバーが含まれています。 また、結びつけられているテーブルに新しく列が追加されたかどうかを動的にチェックし、追加された列をレコードセットのデータ メンバーではなく、動的に割り当てられたメモリに結びつけるための補足コードも含まれています。

このトピックでは、その他の動的バインディング (テーブルや列の削除など) に対応する方法については説明しません。 このような変更を行うためには、ODBC API 関数を直接使用する必要があります。 詳細については、MSDN ライブラリ CD の『ODBC SDK Programmer's Reference』を参照してください。

列を動的に結びつける方法

列を動的に結びつけるには、追加する列の名前を把握する (または決定できる) 必要があります。 また、追加するフィールド データ メンバーに対するメモリを割り当てて名前と型を指定し、追加する列の数を指定する必要があります。

次に、2 つのレコードセットを使う方法について説明します。 第 1 のレコードセットは、メイン レコードセットと呼ばれ、目的のテーブルからレコードを選択します。 第 2 のレコードセットは、列レコードセットと呼ばれ、目的のテーブルに含まれる列に関する情報を得るために使われます。

一般的なプロセス

一般的には、次の手順に従って作業します。

  1. メイン レコードセット オブジェクトを構築します。

    必要に応じて、開いている CDatabase オブジェクトにポインターを渡します。または、その他の方法で、列レコードセットに接続情報を指定することもできます。

  2. 列を動的に追加します。

    次の「列の追加」の手順に従ってください。

  3. メイン レコードセットを開きます。

    メイン レコードセットは、レコードを選択し、レコード フィールド エクスチェンジを使って静的な列 (レコードセット フィールド データ メンバーに結びつけられた列) と動的な列 (動的に確保したメモリに結びつけられる列) の両方を処理します。

列の追加

実行時に追加された列を動的に結びつけるには、次の手順に従ってください。

  1. 目的のテーブルに、実行時の時点でどのような列が存在するのかをチェックします。 これによって得られた情報に基づいて、レコードセット クラスのデザイン時以降にテーブルに追加された列の一覧を作成します。

    テーブルに追加された列に関する情報 (列名やデータ型など) をデータ ソースで検索するための列レコードセット クラスを作成することをお勧めします。

  2. 新しいフィールド データ メンバーのためのメモリを確保します。 メイン レコードセット クラスには、追加された列のためのフィールド データ メンバーは用意されていないので、列の名前、戻り値、およびデータ型 (各列のデータ型が異なる場合) に関する情報を保存するための場所を用意する必要があります。

    この処理を行う 1 つのアプローチは、いくつかの動的リストを作成する方法です。第 1 の動的リストに列名を保存し、第 2 の動的リストに列の戻り値を保存し、(必要ならば) 第 3 の動的リストにデータ型を保存します。 これらのリスト、特に値のリストは、結合用の情報を保存するための場所になります。 これらのリストの構成を次の図に示します。

    動的に結びつける列のリストを生成する方法

    動的にバインドされたビルド リスト列

  3. 追加された列に対する RFX 関数呼び出しコードをメイン レコードセットのメンバー関数 DoFieldExchange の中に記述します。 これらの RFX 関数呼び出しは、追加された列を含むレコードを抽出し、列とレコードセットのデータ メンバー間、または列と動的に確保されたメモリ間を結びつけます。

    この処理を行う 1 つの方法は、メイン レコードセットの関数 DoFieldExchange の中にループを設けて、一連の追加列に対して該当する RFX 関数を呼び出す方法です。 RFX 関数を呼び出すたびに、列名リスト内の列名、および列値を格納するメモリ アドレスをパラメーターとして渡します。

列のリスト

使用する必要のある 4 つのリストを次に示します。

  • 現在のテーブル列 (図のリスト 1)
    データ ソースのテーブル内に現在ある列のリストです。 このリストは、レコードセット内で現在結びつけられている列のリストと一致する場合があります。

  • 既に結びつけられているレコードセットの列 (図のリスト 2)
    レコードセットに結びつけられている列のリストです。 これらの列は、関数 DoFieldExchange の中に RFX ステートメントを既に持っています。

  • 動的に結びつける列 (図のリスト 3)
    テーブルだけにあり、レコードセットにない列のリストです。 これらの列は動的に結びつけられます。

  • 動的な列の値 (図のリスト 4)
    動的に結びつける列から取得した値の格納場所のリストです。 このリストの各要素は、"動的に結びつける列" の要素と一対一に対応します。

リストの構築

一般的な方法を理解したところで、細部を見ていくことにします。 このトピックの残りの部分では、「列のリスト」で紹介したリストを構築する方法について説明します。 必要な手順は以下のとおりです。

  • レコードセットにない列名の決定

  • テーブルに新しく加わった列のための動的領域の作成

  • 新しい列のための RFX 呼び出しの動的追加

レコードセットにない列名の決定

既にメイン レコードセットに結びつけられている列のリスト ("既に結びつけられているレコードセット列"、図のリスト 2 を参照) を作成します。 その後、データ ソースのテーブルにあってメイン レコードセットにない列の名前を含むリスト ("現在のテーブル列" と "既に結びつけられているレコードセットの列" から派生する、"動的に結びつける列") を作成します。

レコードセット内にない列の名前を判定するには ("動的に結びつける列" (リスト 3) の作成)

  1. 既にメイン レコードセットに結びつけられている列のリスト ("既に結びつけられているレコードセットの列" (リスト 2)) を作成します。

    この処理を行う 1 つの方法は、デザイン時にリスト 2 を作成しておく方法です。 レコードセットの関数 DoFieldExchange の RFX 関数呼び出しを調べると、列名を確認できます。 これらの列名を使ってリストを初期化します。

    たとえば、図では、"既に結びつけられているレコードセット列" (リスト 2) には 3 つの要素があります。 リスト 1 にあってリスト 2 で欠けているのは "Phone" です。

  2. "現在のテーブル列" (リスト 1) と "既に結びつけられているレコードセット列" (リスト 2) を比較して "動的に結びつける列" (リスト 3) を作成します。

    比較を行う 1 つの方法は、ループによって "現在のテーブル列" と "既に結びつけられているレコードセット列" の要素を 1 つずつ調べる方法です。 "現在のテーブル列" にあって "既に結びつけられているレコードセット列" に欠けている要素を "動的に結びつける列" に格納します。"動的に結びつける列" は、動的にメモリを確保する必要のある列のリストです。

    たとえば、図のリスト "動的に結びつける列" (リスト 3) には要素 "Phone" が格納されています。これは、リスト 1 (テーブル) にあってリスト 2 (レコードセット) に欠けている列です。

  3. "動的な列の値" (リスト 4) を作成します (図のリスト 4 参照)。リスト 4 は、"動的に結びつける列" (リスト 3) に名前が格納されている各列の値を保存するためのリストです。

    このリストの各要素は、新しいレコードセット フィールド データ メンバーの役割を果たします。 これらは、動的な列が結びつけられた格納場所です。 このリストについては、「列のリスト」を参照してください。

新しい列の領域の作成

動的に結びつけられた列のための格納場所を用意します。 つまり、それぞれの列の値を格納する場所のリストを作成します。 これらの格納場所は、通常の方法で結びつけられた列を格納するレコードセットのメンバー変数に相当します。

新しく追加された列の値を保存する場所を動的に作成するには ("動的な列の値" (リスト 4) の作成)

  • リスト 3 ("動的に結びつける列") と同数の要素を持つリスト 4 ("動的な列の値") を作成します。

    たとえば、図の "動的な列の値" には 1 つの CString 型オブジェクト要素が含まれています。この要素には、現在のレコードの "phone" フィールドの値 "555-1212" が格納されます。

    多くの場合、リスト 4 の要素は CString 型にします。 さまざまな型を持つ複数の列を処理する場合は、さまざまな型の要素を保持できるリストが必要です。

この手順によって 2 つの重要なリストが得られます。"動的に結びつける列" (リスト 3) には列名が格納され、"動的な列の値" (リスト 4) には現在のレコードの各列の値が格納されます。

ヒント

新しく追加された複数の列のデータ型が異なる場合は、列リストの各要素の型を記録するためにもう 1 つのリストが必要です。 このリストでは、必要に応じて AFX_RFX_BOOLAFX_RFX_BYTE などの定数を使用できます。 これらの定数は、AFXDB.H で定義されています。 このリストの型は、列データの型を表す方法によって決定されます。

列を結びつける RFX 関数呼び出しの追加

最後に、関数 DoFieldExchange の中に RFX 関数呼び出しを作成して、新しい列の動的な連結を準備します。

追加された列に対する RFX 関数を動的に呼び出すには

  • メイン レコードセットのメンバー関数 DoFieldExchange に、追加された各列 ("動的に結合する列" リスト) を処理するためのループを設けます。 各ループごとに、"動的に結合する列" リストから列名を取り出し、"動的な列の値" リストから列の値を取り出します。 取り出した値は、該当するデータ型の RFX 関数に渡します。 このリストについては、「列のリスト」を参照してください。

通常は、CString 型のオブジェクトをリストから取り出して、RFX_Text 関数呼び出しのパラメーターとして与えます。この例を次に示します。ここでは、"動的に結びつける列" は CStringList 型リスト m_listName、"動的な列の値" は CStringList 型リスト m_listValue として表されています。

RFX_Text( pFX, 
            m_listName.GetNext( posName ), 
            m_listValue.GetNext( posValue ));

RFX 関数の詳細については、『MFC リファレンス』の「MFC マクロとグローバル」を参照してください。

ヒント

追加された複数の列の型が異なる場合は、ループ内で switch ステートメントを使用して、型ごとに適切な RFX 関数を呼び出します。

フレームワークが Open 処理の中で DoFieldExchange を呼び出してレコードセットと列を結びつけるときは、まず静的な列に対する RFX 関数が呼び出されて、静的な列が結びつけられます。 次に、ループ処理によって、動的な列に対する RFX 関数が繰り返し呼び出されます。

参照

概念

レコードセット (ODBC)

レコードセット: 大量のデータの処理 (ODBC)