次の方法で共有


レコードセット: AddNew、Edit、Delete の動作のしくみ (ODBC)

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

このトピックでは、CRecordset クラスのメンバー関数 AddNewEdit、および Delete がどのように機能するのかについて説明します。 取り上げるトピックは次のとおりです。

Note

このトピックの内容は、バルク行フェッチが実装されていない CRecordset の派生オブジェクトを対象にしています。 バルク行フェッチを使用する場合は、「レコードセット: レコードの一括フェッチ (ODBC)」を参照してください。

補足として、「レコード フィールド エクスチェンジ: RFX の動作のしくみ」を参照してください。この記事では、更新操作における RFX の対応する役割について説明しています。

レコードの追加

レコードセットに新しいレコードを追加するには、レコードセットの AddNew メンバー関数を呼び出し、新しいレコードのフィールド データ メンバーの値を設定して、Update メンバー関数を呼び出してレコードをデータ ソースに書き込む必要があります。

AddNew を呼び出す前提条件として、レコードセットは読み取り専用として開かないようにする必要があります。 メンバー関数 CanUpdate および CanAppend を使用すると、これらの条件を確認できます。

AddNew を呼び出す場合:

  • 操作が取り消された場合に内容を復元できるよう、編集バッファー内のレコードが格納されます。

  • 後で変更を検出できるよう、フィールド データ メンバーにフラグが設定されます。 フィールド データ メンバーもクリーン (変更なし) とマークされ、Null に設定されます。

AddNew を呼び出した後、編集バッファーは新しい空のレコードを表し、値を入力する準備ができた状態になります。 これを行うには、値を手動で割り当てて設定します。 フィールドの実際のデータ値を指定する代わりに、SetFieldNull を呼び出して Null 値を指定することもできます。

変更をコミットするには、Update を呼び出します。 新しいレコードに対して Update を呼び出す場合:

  • ODBC ドライバーが ::SQLSetPos ODBC API 関数をサポートしている場合、MFC はその関数を使用してデータ ソースにレコードを追加します。 ::SQLSetPos を使用した場合、MFC では、SQL ステートメントを作成して処理する必要がないので、より効率的にレコードを追加できます。

  • ::SQLSetPos を使用できない場合、MFC では次の手順が実行されます。

    1. 変更が検出されなかった場合、Update は何も実行せず、0 を返します。

    2. 変更がある場合は、Update は SQL INSERT ステートメントを構築します。 すべてのダーティ フィールド データ メンバーで表される列が、INSERT ステートメントにリストされます。 列を強制的に含めるには、SetFieldDirty メンバー関数を呼び出します。

      SetFieldDirty( &m_dataMember, TRUE );
      
    3. Update は新しいレコードをコミットします。INSERT ステートメントが実行され、トランザクションが進行中でない限り、レコードがデータ ソースのテーブル (およびレコードセット (スナップショットではない場合)) にコミットされます。

    4. 格納されたレコードは編集バッファーへと復元されます。 AddNew 呼び出しの前に最新であったレコードは、INSERT ステートメントが正常に実行されたかどうかに関係なく、再び最新の状態になります。

    ヒント

    新しいレコードを完全に制御するには、次の方法を使用します。値を持つことになるすべてのフィールドの値を設定し、フィールドへのポインターとパラメーター TRUE (既定値) を指定して SetFieldNull を呼び出すことによって、Null のままにするフィールドを明示的に設定します。 フィールドがデータ ソースに書き込まれないようにしたい場合は、フィールドへのポインターとパラメーター FALSE を指定して SetFieldDirty を呼び出し、フィールドの値を変更しないようにします。 フィールドを Null にできるかどうかを確認するには、IsFieldNullable を呼び出します。

    ヒント

    レコードセット データ メンバーが値をいつ変更したかを検出するために、MFC では、レコードセットに格納できる各データ型に適した PSEUDO_NULL 値が使用されます。 フィールドを明示的に PSEUDO_NULL 値に設定する必要がある場合で、フィールドが既に Null とマークされている場合は、SetFieldNull を呼び出し、最初のパラメーターでフィールドのアドレスを渡し、2 番目のパラメーターで FALSE を渡す必要があります。

追加されたレコードの表示

レコードセットに追加されたレコードはいつ表示されるのでしょうか? 追加されたレコードは、次の 2 つの要因によって、表示される場合と表示されない場合があります。

  • ドライバーが実行できる機能。

  • フレームワークで利用できる機能。

ODBC ドライバーが ::SQLSetPos ODBC API 関数をサポートしている場合、MFC はその関数を使用してレコードを追加します。 ::SQLSetPos を使用した場合、追加されたレコードは更新可能な MFC レコードセットに対して表示されます。 関数に対するサポートがない場合、追加されたレコードは表示されません。それらを表示するには、Requery を呼び出す必要があります。 ::SQLSetPos を使用した方が、より効率的でもあります。

既存のレコードの編集

レコードセット内の既存のレコードを編集するには、レコードにスクロールし、レコードセットの Edit メンバー関数を呼び出して、新しいレコードのフィールド データ メンバーの値を設定し、Update メンバー関数を呼び出して、変更されたレコードをデータ ソースに書き込む必要があります。

Edit を呼び出す前提条件として、レコードセットは更新可能であり、1 つのレコード上である必要があります。 メンバー関数 CanUpdate および IsDeleted を使用すると、これらの条件を確認できます。 現在のレコードがまだ削除されていないことも条件となります。また、レコードセット内にレコードが存在する必要があります (IsBOFIsEOF のどちらも 0 を返します)。

Edit を呼び出すと、編集バッファー (現在のレコード) 内のレコードが格納されます。 格納されたレコードの値は、後でフィールドが変更されたかどうかを検出するために使用されます。

Edit を呼び出した後も、編集バッファーは引き続き現在のレコードを表しますが、フィールド データ メンバーへの変更を受け入れる準備が整った状態になります。 レコードを変更するには、編集するフィールド データ メンバーの値を手動で設定します。 フィールドの実際のデータ値を指定する代わりに、SetFieldNull を呼び出して Null 値を指定することもできます。 変更をコミットするには、Update を呼び出します。

ヒント

AddNew または Edit モードから抜け出すには、AFX_MOVE_REFRESH パラメーターを指定して Move を呼び出します。

Update を呼び出す前提条件として、レコードセットが空であってはいけません。また、現在のレコードが削除されていないことも条件となります。 IsBOFIsEOF、および IsDeleted はすべて 0 を返します。

編集されたレコードに対して Update を呼び出す場合:

  • ODBC ドライバーが ::SQLSetPos ODBC API 関数をサポートしている場合、MFC はその関数を使用してデータ ソースにレコードを更新します。 ::SQLSetPos を使用した場合、ドライバーは編集バッファーをサーバー上の対応するレコードと比較し、2 つが異なる場合にはサーバー上のレコードを更新します。 ::SQLSetPos を使用した場合、MFC では、SQL ステートメントを作成して処理する必要がないので、より効率的にレコードを更新できます。

    または

  • ::SQLSetPos を使用できない場合、MFC では次の手順が実行されます。

    1. 変更がなかった場合、Update は何も行いません。0 が返されます。

    2. 変更がある場合は、Update は SQL UPDATE ステートメントを構築します。 UPDATE ステートメントに示される列は、変更されたフィールド データ メンバーに基づいて決まります。

    3. Update は、変更をコミットします。UPDATE ステートメントが実行され、データ ソースでレコードが変更されますが、トランザクションが進行中の場合はコミットされません (トランザクションが更新に与える影響について詳しくは、「トランザクション: レコードセットからのトランザクション実行 (ODBC)」をご覧ください)。 ODBC にはレコードのコピーが保持されます (このコピーも変更されます)。

    4. AddNew のプロセスとは異なり、この Edit プロセスでは格納されているレコードは復元されません。 編集されたレコードが、そのまま現在のレコードとなります。

    注意事項

    Update を呼び出してレコードセットを更新する前に、テーブルの主キーを構成するすべての列 (または、テーブルで一意のインデックスを構成するすべての列か、行を一意に識別するための十分な列) がレコードセットに含まれていることを確認してください。 場合によっては、フレームワークは、レコードセット内で選択されている列だけに基づいてテーブル内の更新するレコードを特定します。 必要なすべての列がない場合、テーブル内で複数のレコードが更新される可能性があります。 この場合は、Update を呼び出した結果として例外がスローされます。

    ヒント

    AddNew または Edit を呼び出す前に、そのいずれかの関数を呼び出していて、それが Update の呼び出しよりも前であった場合は、格納されたレコードによって編集バッファーが更新され、作業中の新しいレコードや編集済みレコードが置き換えられます。 この動作を行うと、AddNew または Edit が中止され、新しい関数が開始されます。作業中のレコードに問題があることがはっきりしている場合は、Edit または AddNew を再度呼び出してください。

レコードの削除

レコードセットからレコードを削除するには、レコードにスクロールし、レコードセットの Delete メンバー関数を呼び出す必要があります。 AddNewEdit とは異なり、Delete では、Update への一致する呼び出しは必要ありません。

Delete を呼び出す前提条件として、レコードセットは更新可能であり、1 つのレコード上である必要があります。 メンバー関数 CanUpdateIsBOFIsEOF、および IsDeleted を使用すると、これらの条件を確認できます。

Delete を呼び出す場合:

  • ODBC ドライバーが ::SQLSetPos ODBC API 関数をサポートしている場合、MFC はその関数を使用してデータ ソースにレコードを削除します。 通常は、::SQLSetPos を使用する方が SQL を使用するよりも効率的です。

    または

  • ::SQLSetPos を使用できない場合、MFC では次の手順が実行されます。

    1. 編集バッファー内の現在のレコードは、AddNewEdit の場合のようにはバックアップされません。

    2. Delete が、レコードを削除する SQL DELETE ステートメントを構築します。

      編集バッファー内の現在のレコードは、AddNewEdit の場合のようには格納されません。

    3. Delete が削除をコミットします。DELETE ステートメントが実行されます。 レコードはデータ ソースで削除済みとしてマークされます。レコードがスナップショットの場合は、ODBC でマークされます。

    4. 削除されたレコードの値はレコードセットのフィールド データ メンバーに残りますが、フィールド データ メンバーは Null としてマークされ、レコードセットのメンバー関数 IsDeleted は 0 以外の値を返します。

    Note

    レコードを削除したら、別のレコードまでスクロールし、編集バッファーに新しいレコードのデータを補充してください。 Delete を再度呼び出したり、Edit を呼び出したりするとエラーになります。

更新操作で使用される SQL ステートメントについて詳しくは、「SQL」をご覧ください。

関連項目

レコードセット (ODBC)
レコードセット: 更新処理の詳細 (ODBC)
レコード フィールド エクスチェンジ (RFX)