次の方法で共有


レコードセット: 定義済みクエリを利用したクラスの宣言 (ODBC)

Note

MFC ODBC コンシューマー ウィザードは、Visual Studio 2019 以降では利用できません。 引き続き、コンシューマーを手動で作成することはできます。

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

このトピックでは、定義済みクエリ (Microsoft SQL Server のように、ストアド プロシージャとも呼ばれます) のレコードセット クラスを作成する方法について説明します。

Note

このトピックの内容は、バルク行フェッチが実装されていない CRecordset の派生オブジェクトを対象にしています。 バルク行フェッチが実装されている場合も、プロセスはとてもよく似ています。 バルク行フェッチが実装されているレコードセットとそうでないものとの違いを理解するには、「レコードセット: レコードのバルク フェッチ (ODBC)」を参照してください。

一部のデータベース管理システム (DBMS) を使用すると、定義済みクエリを作成し、関数のようにプログラムから呼び出すことができます。 クエリは、名前を持ち、パラメーターを受け取る場合があり、レコードを返す場合があります。 このトピックの手順では、レコードを返す (そして、おそらくはパラメーターを受け取る) 定義済みクエリを呼び出す方法について説明します。

データベース クラスでは、定義済みクエリの更新はサポートされていません。 スナップショット定義済みクエリとダイナセット定義済みクエリの違いは、更新可能かどうかではなく、他のユーザー (または、プログラム内の他のレコードセット) によって行われた変更が自分のレコードセットに表示されるかどうかです。

ヒント

レコードを返さない定義済みクエリは、レコードセットがなくても呼び出すことができます。 以下で説明するように SQL ステートメントを準備しますが、それを実行するには CDatabase メンバー関数の ExecuteSQL を呼び出します。

1 つのレコードセット クラスを作成して定義済みクエリの呼び出しを管理できますが、自分で作業しなければならないことがいくつかあります。 この目的専用のクラスの作成は、ウィザードではサポートされていません。

定義済みクエリ (ストアド プロシージャ) を呼び出すためのクラスを作成するには

  1. [クラスの追加] から MFC ODBC コンシューマー ウィザードを使って、クエリによって返される列の最も多くに関係するテーブルのレコードセット クラスを作成します。 これにより始めることができます。

  2. クエリによって返されますが、ウィザードで自動的には作成されなかった、すべてのテーブルのすべての列のフィールド データ メンバーを手動で追加します。

    たとえば、クエリによって 3 つの列が返され、それぞれに 2 つの追加テーブルがある場合は、クラスに (適切なデータ型の) 6 つのフィールド データ メンバーを追加します。

  3. 追加する各フィールド データ メンバーのデータ型に対応する RFX 関数の呼び出しを、クラスの DoFieldExchange メンバー関数に手作業で追加します。

    Immediately before these RFX calls, call <MSHelp:link keywords="_mfc_CFieldExchange.3a3a.SetFieldType" TABINDEX="0">SetFieldType</MSHelp:link>, as shown here:
    pFX->SetFieldType( CFieldExchange::outputColumn );
    

    Note

    結果セットで返される列のデータ型と順序がわかっている必要があります。 DoFieldExchange 内での RFX 関数の呼び出しの順序は、結果セットの列の順序と一致している必要があります。

  4. レコードセット クラスのコンストラクターに、新しいフィールド データ メンバーの初期化を手作業で追加します。

    m_nFields データ メンバーの初期化の値を増分する必要もあります。 ウィザードで初期化は記述されますが、自動的に追加されるフィールド データ メンバーのものだけです。 次に例を示します。

    m_nFields += 6;
    

    CLongBinary やバイト配列など、一部のデータ型はここでは初期化できません。

  5. クエリがパラメーターを受け取る場合は、各パラメーターのパラメーター データ メンバー、それぞれに対する RFX 関数呼び出し、およびそれぞれの初期化を追加します。

  6. この手順のステップ 4 で追加フィールドに対して m_nFields で行ったのと同じように、追加するパラメーターごとに m_nParams を増分する必要があります。 詳細については、「レコードセット: パラメーターを利用したレコードセット (ODBC)」を参照してください。

  7. 次の形式で SQL ステートメントの文字列を手作業で記述します。

    {CALL proc-name [(? [, ?]...)]}
    

    CALL は ODBC のキーワードであり、proc-name はデータ ソースで認識されているクエリの名前です。"?" の項目は実行時にレコードセットに提供するパラメーター値のプレースホルダーです (ある場合)。 次の例では、1 つのパラメーターに対してプレースホルダーを準備しています。

    CString mySQL = "{CALL Delinquent_Accts (?)}";
    
  8. レコードセットを開くコードで、レコードセットのパラメーター データ メンバーの値を設定した後、Open メンバー関数を呼び出して、lpszSQL パラメーターに SQL 文字列を渡します。 またはその代わりに、独自のクラスの GetDefaultSQL メンバー関数によって返される文字列を置き換えます。

次の例では、Delinquent_Accts という名前の定義済みクエリを呼び出す手順を示します。このクエリは販売地域番号のパラメーターを 1 つ受け取ります。 このクエリでは、3 つの列 Acct_NoL_NamePhone が返されます。 すべての列は Customers テーブルからのものです。

次のレコードセットでは、クエリから返される列と、実行時に要求される販売地域番号のパラメーターに対する、フィールド データ メンバーが指定されています。

class CDelinquents : public CRecordset
{
// Field/Param Data
    LONG m_lAcct_No;
    CString m_strL_Name;
    CString m_strPhone;
    LONG m_lDistParam;
    // ...
};

このクラスの宣言は、手作業で追加した m_lDistParam メンバーを除き、ウィザードによって記述されたとおりのものです。 他のメンバーはここでは示されていません。

次の例では、CDelinquents コンストラクターでのデータ メンバーの初期化を示します。

CDelinquents::CDelinquents(CDatabase* pdb)
   : CRecordset(pdb)
{
    // Wizard-generated params:
    m_lAcct_No = 0;
    m_strL_Name = "";
    m_strPhone = "";
    m_nFields = 3;
    // User-defined params:
    m_nParams = 1;
    m_lDistParam = 0;
}

m_nFieldsm_nParams に対する初期化に注意してください。 m_nFields はウィザードによる初期化で、m_nParams はユーザーによる初期化です。

次の例では、CDelinquents::DoFieldExchange での RFX 関数を示します。

void CDelinquents::DoFieldExchange(CFieldExchange* pFX)
{
    pFX->SetFieldType(CFieldExchange::outputColumn);
    RFX_Long(pFX, "Acct_No", m_lAcct_No);
    RFX_Text(pFX, "L_Name", m_strL_Name);
    RFX_Text(pFX, "Phone", m_strPhone);
    pFX->SetFieldType(CFieldExchange::param);
    RFX_Long(pFX, "Dist_No", m_lDistParam);
}

3 つの返される列に対して RFX 関数の呼び出しを行うだけでなく、このコードでは実行時に渡すパラメーターのバインドが管理されています。 パラメーターは、Dist_No (地域番号) 列に対応しています。

次の例では、SQL 文字列を設定する方法と、それを使ってレコードセットを開く方法を示します。

// Construct a CDelinquents recordset object
CDelinquents rsDel( NULL );
CString strSQL = "{CALL Delinquent_Accts (?)}"
// Specify a parameter value (obtained earlier from the user)
rsDel.m_lDistParam = lDistrict;
// Open the recordset and run the query
if( rsDel.Open( CRecordset::snapshot, strSQL ) )
    // Use the recordset ...

このコードでは、スナップショットが作成され、前にユーザーから取得したパラメーターにそれが渡され、定義済みのクエリが呼び出されています。 クエリを実行すると、指定した販売地域のレコードが返されます。 各レコードには、アカウント番号、顧客の姓、および顧客の電話番号の列が含まれています。

ヒント

ストアド プロシージャからの戻り値 (出力パラメーター) を処理することが必要な場合があります。 詳細と例については、「CFieldExchange::SetFieldType」を参照してください。

関連項目

レコードセット (ODBC)
レコードセット: クエリの再実行 (ODBC)
レコードセット: テーブルにアクセスするレコードセット クラスの宣言 (ODBC)
レコードセット: 結合 (ODBC)